2014-11-06 2 views
2

Я пытаюсь создать пользовательский NSMutableSet, который не использует стандартные isEqual: и hash селекторами на объектах.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

Как создать подкласс NSObject, который использует NSMutableSet. Таким образом, вы можете перенаправить большинство функций на набор и просто сделать свою собственную равную функцию и прочее ... – Fogmeister

ответ

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]]; 

, конечно, йо u также нужно обернуть перед поиском NSMutableSet.

+0

Спасибо, я об этом не думал. Хотя я не думаю, что это действительно проще, это выглядит намного безопаснее, по крайней мере, пока я не подтвержу, что код, который я написал, хорош. – deadbeef

1

Ваш код выглядит отлично. Все мосты используют правильную семантику собственности. Я не вижу никаких очевидных ошибок.

Я думаю, что это решение лучше, чем использование объекта-обертки.

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.

Смежные вопросы