Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在macOS Objective-C应用程序中,我将NSMutableSet子类化,用于强制执行不同于isEqual的等式。我的实现好吗?_Objective C_Xcode_Nsmutableset_Nsrunningapplication - Fatal编程技术网

在macOS Objective-C应用程序中,我将NSMutableSet子类化,用于强制执行不同于isEqual的等式。我的实现好吗?

在macOS Objective-C应用程序中,我将NSMutableSet子类化,用于强制执行不同于isEqual的等式。我的实现好吗?,objective-c,xcode,nsmutableset,nsrunningapplication,Objective C,Xcode,Nsmutableset,Nsrunningapplication,在我的macOS Objective-C应用程序中,我创建了NSMutableSet的一个子类。我想要实现的是一个NSMutableSet,它不使用isEqual:作为比较策略。具体来说,该集合将包含NSRunningApplication类型的对象,我希望该集合能够基于对象束标识符的相等性工作。以下是我的实施: 头文件: #import <Cocoa/Cocoa.h> NS_ASSUME_NONNULL_BEGIN @interface BundleIdentifierAwar

在我的macOS Objective-C应用程序中,我创建了NSMutableSet的一个子类。我想要实现的是一个NSMutableSet,它不使用isEqual:作为比较策略。具体来说,该集合将包含NSRunningApplication类型的对象,我希望该集合能够基于对象束标识符的相等性工作。以下是我的实施:

头文件:

#import <Cocoa/Cocoa.h>

NS_ASSUME_NONNULL_BEGIN

@interface BundleIdentifierAwareMutableSet : NSMutableSet 

@property (atomic, strong) NSMutableSet     *backStorageMutableSet;
@property (atomic, strong) NSMutableArray     *backStorageMutableArray;

@end

NS_ASSUME_NONNULL_END
这似乎是可行的,事实上,在适用的情况下,普通NSMutableSet不会认为两个成员相等的Xcode日志。我想把这个实现带到生产应用程序中,但我恐怕没有考虑一些重要的事情,因为这是我第一次将NSMutableSet子类化。例如,我担心以下方法:

- (NSEnumerator *)objectEnumerator {
    
    self.backStorageMutableSet = [NSMutableSet setWithArray:self.backStorageMutableArray];
    
    return [self.backStorageMutableSet objectEnumerator];
    
}
这是我唯一一次使用backStorageMutableSet,因为其余的都备份到了数组中。这是好的还是会带来麻烦?子类的其他部分会带来问题吗?任何帮助都将不胜感激。谢谢,不要这样做。子类化集合应该是最后的手段。它可能会对性能产生影响。。。尝试使用尽可能高的抽象,如果出于某种原因它对您不起作用,就降低它

包装器对象 将NSRunningApplication包装到另一个对象中,并提供您自己的hash&isEqual:methods

应用程序.h:

@接口应用程序:NSObject @属性非原子、强、只读、非空NSRunningApplication*应用程序; @结束 申请表m:

@接口应用程序 @属性非原子、强、非空NSRunningApplication*应用程序; @结束 @实施应用 -非Null instancetypeinitWithRunningApplication:NSRunningApplication*\u非NullApplication{ 如果self=[super init]==nil{ // https://developer.apple.com/documentation/objectivec/nsobject/1418641-init?language=objc // //NSObject类中定义的init方法不进行初始化;它只是 //返回self。就可空性而言,调用方可以假定NSObject //init的实现不返回nil。 返回零; } 自我应用=应用; 回归自我; } // https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418795-isequal?language=objc -BOOLisEqual:idobject{ if![object iskindof类:[应用程序类]]{ 返回否; } 应用程序*应用程序=应用程序*对象; 返回[self.application.bundleIdentifier isEqualToString:app.application.bundleIdentifier]; } // https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418859-hash?language=objc -恩苏尔哈什{ 返回self.application.bundleIdentifier.hash; } @结束 免费桥接和CFMutableSetRef

CFSET与NSSET桥接,CFMUBABLSET与NSMutabelEt等桥接,这意味着您可以通过核心基础创建一个集合。 API,然后将其用作NSSet,例如。核心基础是强大的基础 向您公开更多内容的框架

您可以为CFSet提供一组自定义回调

/*! @typedef CFSetCallBacks 结构,其中包含CFSet的回调。 @field version传递的结构类型的版本号 作为CFSet创建函数的参数。这 结构是版本0。 @字段retain用于为上的集合添加retain的回调 值,因为它们被放入集合中。此回调返回 要存储在集合中的值,通常为 参数传递到此回调,但可能是另一个 值,如果集合中应存储不同的值。 集合的分配器作为第一个参数传递。 @字段release用于删除先前添加的保留的回调 对于从中删除的“设置自”值 设置集合的分配器作为第一个分配器传递 论点 @字段CopyScription用于创建描述性 集合中每个值的字符串表示形式。这是 由CFCopyDescription函数使用。 @字段等于用于比较集合中的值的回调 某些操作的等式。 @字段哈希用于比较集合中的值的回调 某些操作的唯一性。 */ 类型定义结构{ 索引版本; CFSetRetainCallBack retain; cfsetrelease回调释放; cfSetCopyDescription回调copyDescription; CFSetEqualCallBack相等; cfsethashcallbackhash; }CFSetCallBacks; 有预定义的回调集,如:

/*! @常量kCFTypeSetCallBacks 预定义的CFSetCallBacks结构,包含一组回调 适合在CFSet中的值都是CFTYPE时使用。 */ 出口 常数CFSetCallB 确认kCFTypeSetCallBacks; 这意味着您不必提供所有这些,但您可以自由修改其中的一些。让我们准备两个回调函数:

//typedef CFHashCode*CFSetHashCallBackconst void*值; CFHashCode runningApplicationBundleIdentifierHashconst void*值{ NSRunningApplication*应用程序=u桥NSRunningApplication*值; 返回[application.bundleIdentifier哈希]; } //typedef Boolean*CFSetEqualCallBackconst void*value1,const void*value2; 布尔运行应用程序BundleIdentifier equalConst void*value1,const void*value2{ NSRunningApplication*application1=u桥NSRunningApplication*value1; NSRunningApplication*application2=u桥NSRunningApplication*value2; 返回[application1.bundleIdentifier IsequalString:application2.bundleIdentifier]; } 您可以通过以下方式使用它们:

-NSMutableSet*\U NULLABLEBUNDLEIDENTIFIERAWAREMUTABLESETWITH容量:NSUPINTEGERCAPACITY{ //>预定义的CFSetCallBacks结构,包含一组回调 //>适合在CFSet中的值都是CFTYPE时使用。 // //这意味着您不应该为保留、释放、回调而烦恼, //他们已经准备好了。 // //CFSetCallbacks可以在堆栈上,因为此结构是在 //CFSetCreateMutable函数。 CFSetCallBacks callbacks=kCFTypeSetCallBacks; //仅覆盖哈希和相等回调 callbacks.hash=runningApplicationBundleIdentifierHash; callbacks.equal=运行ApplicationBundleIdentifierequal; //尝试创建一个可变集。 CFMutableSetRef set=cfsetCreateMuttableKCfallocatorDefault、容量和回调; 如果set==NULL{ //失败,请执行一些错误处理或仅返回nil 返回零; } //将所有权转移到Obj-C&ARC=>无需调用CFRelease return uu bridge u transfer NSMutableSet*set; } &

NSMutableSet*set=[self-bundleIdentifierAwareMutableSetWithCapacity:50]; [set-addObjectsFromArray:[[NSWorkspace sharedWorkspace]运行应用程序]]; NSLog@%@,已设置; 不要这样做。子类化集合应该是最后的手段。它可能会对性能产生影响。。。尝试使用尽可能高的抽象,如果出于某种原因它对您不起作用,就降低它

包装器对象 将NSRunningApplication包装到另一个对象中,并提供您自己的hash&isEqual:methods

应用程序.h:

@接口应用程序:NSObject @属性非原子、强、只读、非空NSRunningApplication*应用程序; @结束 申请表m:

@接口应用程序 @属性非原子、强、非空NSRunningApplication*应用程序; @结束 @实施应用 -非Null instancetypeinitWithRunningApplication:NSRunningApplication*\u非NullApplication{ 如果self=[super init]==nil{ // https://developer.apple.com/documentation/objectivec/nsobject/1418641-init?language=objc // //NSObject类中定义的init方法不进行初始化;它只是 //返回self。就可空性而言,调用方可以假定NSObject //init的实现不返回nil。 返回零; } 自我应用=应用; 回归自我; } // https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418795-isequal?language=objc -BOOLisEqual:idobject{ if![object iskindof类:[应用程序类]]{ 返回否; } 应用程序*应用程序=应用程序*对象; 返回[self.application.bundleIdentifier isEqualToString:app.application.bundleIdentifier]; } // https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418859-hash?language=objc -恩苏尔哈什{ 返回self.application.bundleIdentifier.hash; } @结束 免费桥接和CFMutableSetRef

CFSET与NSSET桥接,CFMUBABLSET与NSMutabelEt等桥接,这意味着您可以通过核心基础创建一个集合。 API,然后将其用作NSSet,例如。核心基础是强大的基础 向您公开更多内容的框架

您可以为CFSet提供一组自定义回调

/*! @typedef CFSetCallBacks 结构,其中包含CFSet的回调。 @field version传递的结构类型的版本号 作为CFSet创建函数的参数。这 结构是版本0。 @字段retain用于为上的集合添加retain的回调 值,因为它们被放入集合中。此回调返回 要存储在集合中的值,通常为 参数传递到此回调,但可能是另一个 值,如果集合中应存储不同的值。 集合的分配器作为第一个参数传递。 @字段release用于删除先前添加的保留的回调 用于在删除值时设置这些值 从 设置集合的分配器作为第一个分配器传递 论点 @字段CopyScription用于创建描述性 集合中每个值的字符串表示形式。这是 由CFCopyDescription函数使用。 @字段等于用于比较集合中的值的回调 某些操作的等式。 @字段哈希用于比较集合中的值的回调 某些操作的唯一性。 */ 类型定义结构{ 索引版本; CFSetRetainCallBack retain; cfsetrelease回调释放; cfSetCopyDescription回调copyDescription; CFSetEqualCallBack相等; cfsethashcallbackhash; }CFSetCallBacks; 有预定义的回调集,如:

/*! @常量kCFTypeSetCallBacks 预定义的CFSetCallBacks结构,包含一组回调 适合在CFSet中的值都是CFTYPE时使用。 */ 出口 const CFSetCallBacks kCFTypeSetCallBacks; 这意味着您不必提供所有这些,但您可以自由修改其中的一些。让我们准备两个回调函数:

//typedef CFHashCode*CFSetHashCallBackconst void*值; CFHashCode runningApplicationBundleIdentifierHashconst void*值{ NSRunningApplication*应用程序=u桥NSRunningApplication*值; 返回[application.bundleIdentifier哈希]; } //typedef Boolean*CFSetEqualCallBackconst void*value1,const void*value2; 布尔运行应用程序BundleIdentifier equalConst void*value1,const void*value2{ NSRunningApplication*application1=u桥NSRunningApplication*value1; NSRunningApplication*application2=u桥NSRunningApplication*value2; 返回[application1.bundleIdentifier IsequalString:application2.bundleIdentifier]; } 您可以通过以下方式使用它们:

-NSMutableSet*\U NULLABLEBUNDLEIDENTIFIERAWAREMUTABLESETWITH容量:NSUPINTEGERCAPACITY{ //>预定义的CFSetCallBacks结构,包含一组回调 //>适合在CFSet中的值都是CFTYPE时使用。 // //这意味着您不应该为保留、释放、回调而烦恼, //他们已经准备好了。 // //CFSetCallbacks可以在堆栈上,因为此结构是在 //CFSetCreateMutable函数。 CFSetCallBacks callbacks=kCFTypeSetCallBacks; //仅覆盖哈希和相等回调 callbacks.hash=runningApplicationBundleIdentifierHash; callbacks.equal=运行ApplicationBundleIdentifierequal; //尝试创建一个可变集。 CFMutableSetRef set=cfsetCreateMuttableKCfallocatorDefault、容量和回调; 如果set==NULL{ //失败,请执行一些错误处理或仅返回nil 返回零; } //将所有权转移到Obj-C&ARC=>无需调用CFRelease return uu bridge u transfer NSMutableSet*set; } &

NSMutableSet*set=[self-bundleIdentifierAwareMutableSetWithCapacity:50]; [set-addObjectsFromArray:[[NSWorkspace sharedWorkspace]运行应用程序]]; NSLog@%@,已设置;
这不是答案,但您最好在NSRunningApplication周围实现一个包装器对象,该应用程序以您想要的方式实现-isEqual:and-hash,然后使用一组这些包装器对象。您只需要根据bundleIdentifier NSString的相应方法来实现它们?它应该是一个集合还是一个NSMutableDictionary,将捆绑标识作为键作为一个选项?这不是答案,但您最好在NSRunningApplication周围实现一个包装器对象,该应用程序以您想要的方式实现-isEqual:和-hash,然后使用一组这些包装器对象。您只需要根据bundleIdentifier NSString的相应方法来实现它们?它应该是一个集合还是一个NSMutableDictionary,其中捆绑标识作为一个选项?
- (NSEnumerator *)objectEnumerator {
    
    self.backStorageMutableSet = [NSMutableSet setWithArray:self.backStorageMutableArray];
    
    return [self.backStorageMutableSet objectEnumerator];
    
}