2014-11-06 9 views
2

개체에 표준 isEqual:hash 선택기를 사용하지 않는 사용자 지정 NSMutableSet을 만들려고합니다.사용자 지정 isEqual : 및 해시 콜백이있는 NSMutableSet

일반적으로 Parse와 함께 사용하고 싶습니다. 나는 서브 클래스 인스턴스를 포함하는 NSMutableSet을 가지고 있는데, 같은 서브 클래스 인스턴스 인 경우 objectId이라면 동일하다고 생각합니다. PFObject 하위 클래스에서 isEqual:hash을 무시할 수 있지만 모든 내 개체에 해당 기능이 필요하지 않습니다. 게다가, 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 

난 정말 모르겠어요, 그리고 난 CFBridgingRelease()과 같은 핵심 기반 개체 및 기능에 익숙하지 않습니다.

+0

NSMutableSet을 사용하는 NSObject 하위 클래스를 만드는 방법은 어떻습니까? 그렇게하면 대부분의 함수를 집합에 전달할 수 있고 함수와 물건을 등호 할 수 있습니다. – Fogmeister

답변

1

나는 당신의 접근 방식이 불필요하게 복잡하다 생각 : 당신이 NSMutableSet에 배치하기 전에 래퍼 클래스에서 자신의 isEqual:hash 구현을 제공하고, 당신의 PFObject의 포장 수 :

@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 

지금 NSMutableSet에 추가하기 전에 PFObjectWrap으로 개체를 래핑 할 수 : 물론 요의

NSMutableSet *set = [NSMutableSet set]; 
[set addObject:[PFObjectWrap wrap:myObject1]]; 
[set addObject:[PFObjectWrap wrap:myObject2]]; 

NSMutableSet을 검색하기 전에 포장해야합니다.

+0

감사합니다. 비록 그것이 정말로 간단하다고는 생각하지 않지만 적어도 내가 작성한 코드가 좋다는 것을 확인하기 전까지 훨씬 더 안전 해 보입니다. – deadbeef

1

코드가 정상적으로 보입니다. 모든 브릿지 캐스트는 올바른 소유권 의미론을 사용합니다. 나는 명백한 오류를 보지 못했다.

이 솔루션은 래퍼 개체를 사용하는 것보다 낫다고 생각합니다.

0

더 간단히 말해서, 나는 을 NSSet으로 처리 할 수있는 Parse 서브 클래스에 대한 메소드를 만들었습니다.

내가 그것을 사용하는 뷰 컨트롤러에서
- (BOOL)isContainedInArray:(NSArray *)array { 
    for (Tag *tag in array) { 
     if ([self.name isEqualToString:tag.name]) { 
      return YES; 
     } 
    } return NO; 
} 

, 내 NSArray에 추가할지 여부를 결정하기 위해이 방법을 실행합니다. 원래는 isEqualhash을 덮어 썼지 만, 당신이 언급했듯이, 파스의 내부 로직과 충돌을 일으킨다.