我正在尝试创建一个不在对象上使用标准NSMutableSet
和isEqual:
选择器的自定义hash
。
通常我想在Parse中使用它。我有一个包含NSMutableSet
子类实例的PFObject
,如果它们具有相同的objectId
,我认为它们是相同的。
我知道我可以覆盖isEqual:
子类中的hash
和PFObject
,但我不想在所有对象上使用该功能。此外,Parse在内部使用这些方法,所以我不想搞砸它们。
这是我到目前为止所得到的:
#import <Foundation/Foundation.h>
@interface NSMutableSet (Additions)
+ (NSMutableSet *)setWithParseObjectIdIsEqualCallback;
@end
#import "NSMutableSet+Additions.h"
@implementation NSMutableSet (Additions)
static Boolean ParseObjectIdIsEqualCallback(const void *value1, const void *value2)
{
PFObject *obj1 = (__bridge id)value1;
PFObject *obj2 = (__bridge id)value2;
NSCParameterAssert([obj1 isKindOfClass:PFObject.class]);
NSCParameterAssert([obj2 isKindOfClass:PFObject.class]);
NSCParameterAssert([obj1 isMemberOfClass:obj2.class]);
return [obj1.objectId isEqualToString:obj2.objectId];
}
static CFHashCode ParseObjectIdHashCallback(const void *value)
{
PFObject *object = (__bridge id)value;
NSCParameterAssert([object isKindOfClass:PFObject.class]);
return object.objectId.hash;
}
+ (NSMutableSet *)setWithParseObjectIdIsEqualCallback
{
CFSetCallBacks callbacks = kCFTypeSetCallBacks;
callbacks.equal = ParseObjectIdIsEqualCallback;
callbacks.hash = ParseObjectIdHashCallback;
CFMutableSetRef set = CFSetCreateMutable(kCFAllocatorDefault, 0, &callbacks);
return CFBridgingRelease(set);
}
@end
我真的不知道它是否可行或使用是否安全,而且我对Core Foundation对象和函数(如CFBridgingRelease()
)非常不熟悉。
答案 0 :(得分:1)
我认为您的方法不必要地复杂化:您可以在包装器类中提供自己的isEqual:
和hash
实现,并将PFObject
包装在在放入NSMutableSet
:
@interface PFObjectWrap {
PFObject *_obj;
}
-(BOOL)isEqual:(id)other;
-(NSUInteger)hash;
+(PFObject*)wrapped;
-(id)initWithPFObject:(PFObject*)obj;
+(PFObjectWrap)wrap:(PFObject*)obj;
@end
@implementation PFObjectWrap
-(id)initWithPFObject:(PFObject*)obj {
if (self = [super init]) {
_obj = obj;
}
return self;
}
+(PFObjectWrap)wrap:(PFObject*)obj {
return [[PFObjectWrap alloc] initWithPFObject:obj];
}
+(PFObject*)wrapped {
return _obj;
}
-(BOOL)isEqual:(id)other {
// Put your custom implementation here
}
-(NSUInteger)hash {
// Put your custom implementation here
}
@end
现在,您可以在添加到PFObjectWrap
之前将对象包装到NSMutableSet
:
NSMutableSet *set = [NSMutableSet set];
[set addObject:[PFObjectWrap wrap:myObject1]];
[set addObject:[PFObjectWrap wrap:myObject2]];
当然,您还需要在搜索NSMutableSet
之前进行换行。
答案 1 :(得分:1)
您的代码看起来很好。所有桥接演员都使用正确的所有权语义。我没有看到任何明显的错误。
我认为这个解决方案比使用包装器对象更好。
答案 2 :(得分:0)
更简单的是,我在Parse子类上创建了一个方法,允许我将NSArray
视为NSSet
。
- (BOOL)isContainedInArray:(NSArray *)array {
for (Tag *tag in array) {
if ([self.name isEqualToString:tag.name]) {
return YES;
}
} return NO;
}
在我使用它的视图控制器中,运行此方法以确定是否将其添加到我的NSArray
。我最初覆盖了isEqual
和hash
,但正如您所提到的,它会与Parse的内部逻辑产生冲突。