3

我正在尝试创建一个NSMutableSet不使用对象上的标准isEqual:hash选择器的自定义。

通常我想将它与 Parse 一起使用。我有一个NSMutableSet包含PFObject子类实例,如果它们具有相同的objectId. 我知道我可以在我的子类中覆盖isEqual:和,但我不希望我的所有对象都具有该功能。此外,Parse 在内部使用这些方法,所以我不想弄乱它们。hashPFObject

这是我到目前为止提出的:

#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().

4

3 回答 3

1

我认为您的方法不必要地复杂:您可以在包装类中提供自己的isEqual:hash实现,并在放入 s 之前将其包装:PFObjectNSMutableSet

@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

于 2014-11-06T17:57:51.330 回答
1

你的代码看起来不错。所有桥牌转换都使用正确的所有权语义。我没有看到任何明显的错误。

我认为这个解决方案比使用包装对象更好。

于 2014-11-06T18:31:11.130 回答
0

更简单的是,我在我的 Parse 子类上创建了一个方法,让我将 anNSArray视为NSSet.

- (BOOL)isContainedInArray:(NSArray *)array {
    for (Tag *tag in array) {
        if ([self.name isEqualToString:tag.name]) {
            return YES;
        }
    } return  NO;
}

在我使用它的视图控制器中,运行此方法以确定是否将其添加到我的NSArray. 我最初覆盖了isEqualhash但正如你提到的,它与 Parse 的内部逻辑产生了冲突。

于 2015-10-27T15:53:01.667 回答