문제

푸스 배열이있는 클래스 테스트가 있습니다. IVAR을 직접 노출시키지 않고 FOOS에 대한 액세스를 제공하고 싶습니다. 이 KVC를 준수하려고합니다 (또한 KVO 준수를위한 길을 열어주기 위해). 나는 가지고있다:

Test.h

@interface Test : NSObject
{
    NSMutableArray *foos;
}

@property (readonly, copy) NSMutableArray *foos;

@end

test.m

- (id) init
{
    self = [super init];
    if (self != nil)
    {
        foos = [[NSMutableArray array] retain];
    }
    return self;
}

- (NSMutableArray*) foos
{
    return [self mutableArrayValueForKey:@"foos"];
}

- (NSUInteger)countOfFoos
{
    return [foos count];
}

- (id)objectInFoosAtIndex:(NSUInteger)index
{
    return [foos objectAtIndex:index];
}

- (NSArray *)foosAtIndexes:(NSIndexSet *)indexes
{
    return [foos objectsAtIndexes:indexes];
}

- (void)insertObject:(id)key inFoosAtIndex:(NSUInteger)index
{
    [foos insertObject:key atIndex:index];
}

- (void)insertFoos:(NSArray *)foosArray atIndexes:(NSIndexSet *)indexes
{
    [foos insertObjects:foosArray atIndexes:indexes];
}

- (void)removeObjectFromFoosAtIndex:(NSUInteger)index
{
    [foos removeObjectAtIndex:index];
}

- (void)removeFoosAtIndexes:(NSIndexSet *)indexes
{
    [foos removeObjectsAtIndexes:indexes];
}

클라이언트가 foo를 추가하려고 할 때 무한 루프에 들어갑니다.

Test *test = [[Test alloc] init];
NSMutableArray *foos = test.foos;
[foos addObject:@"adding object"]; // infinite loop here

내가 뭘 잘못하고 있죠?

도움이 되었습니까?

해결책

- (NSMutableArray*) foos
{
    return [self mutableArrayValueForKey:@"foos"];
}

액세서는 KVC를 사용하여 부동산의 값에 액세스하지 않아야합니다. 아이디어는 Accessor가 KVC보다 값에 더 가깝기 때문에 KVC는 액세서를 통과한다는 것입니다.

올바른 구현 foos 배열의 사본을 돌연변이하거나 다른 방법으로 반환해야합니다. 내가하는 방법은 다음과 같습니다.

- (NSArray *) foos
{
    return [[foos copy] autorelease];
}

나는 또한 모든 액세서를 공개 할 것입니다. 배열을 돌연변이하거나 특정 인덱스에서 요소를 무작위로 액세스하려는 것은 그렇게 할 수 있습니다. 배열에 직접 액세스하지 않고 액세서를 겪고 있기 때문에 여전히 안전하고 캡슐화됩니다.

코드를 작성할 때 어떤 키에 액세스 할 키를 모르는 경우가 아니라면 KVC 프로토콜 메소드를 직접 사용해야 할 이유는 없습니다. 예를 들어, NIB 로더 또는 코코아 바인딩 시스템을 작성하는 경우 KVC를 사용합니다.

다른 팁

문제는 MutableArrayValueforKey에 의해 리턴 된 프록시 NSMutableARRAY : 먼저 "foos"메소드를 통해 실제 배열을 가져와야한다는 것입니다. 그것은 프록시 nsmutablearray를 반환하는 것이므로 무한 루프로 들어갑니다. 한 가지 해결책은 다른 이름을 사용하는 것입니다.

- (NSMutableArray*) mutableFoos
{
    return [self mutableArrayValueForKey:@"foos"];
}

나는이 문제에 대해 아주 오랜 시간을 보냈고 액세서를 통해 이것을 얻고 싶었습니다. 나는 들어오는 사람들에 대한 답을 명확히하고 싶었습니다. 이것이 내가 한 일입니다.

@property (nonatomic,readonly,getter=getTheFoos) NSMutableArray* foos;

그런 다음 분명히 구현되었습니다.

- (NSMutableArray*)getTheFoos {
    return [self mutableArrayValueForKey:@"foos"];
}

그래도 조심해야했지만 getfoos (문서화되지 않은) KVC 액세서로 보입니다. 이로 인해 동일한 루프로 보냅니다.

그런 다음 kvo에 :

Test* test= [[Test alloc] init];
NSObject* obj= [[NSObject alloc] init];
NSMutableArray* arrTheData= test.foos;

[test.foos insertObject:obj atIndex:0];
[arrFoos insertObject:obj atIndex:0];

Arrfoos 업데이트 된 돌연변이 배열을 읽을 수 있지만 (두 개의 객체가있을 것입니다) KVO를 발사하지 않습니다. 내 모험 어딘가에서, 나는 MutableArearrayvalueforkey에서 돌아온 것이 NSMutableArray*를 반환하지는 않지만 그 하위 클래스를 반환하는 것을 보았습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top