IT박스

삽입 / 제거를 위해 NSMutableArray 관찰

itboxs 2020. 10. 22. 07:49
반응형

삽입 / 제거를 위해 NSMutableArray 관찰


클래스에는 (를 통해 @property) 합성 된 접근자가있는 NSMutableArray 유형의 속성 (및 인스턴스 var)이 있습니다. 다음을 사용하여이 배열을 관찰하는 경우 :

[myObj addObserver:self forKeyPath:@"theArray" options:0 context:NULL];

그런 다음 다음과 같이 배열에 개체를 삽입합니다.

[myObj.theArray addObject:NSString.string];

observeValueForKeyPath ... 알림이 전송 되지 않습니다 . 그러나 다음은 적절한 알림을 보냅니다.

[[myObj mutableArrayValueForKey:@"theArray"] addObject:NSString.string];

mutableArrayValueForKey관찰자에게 알리는 프록시 객체를 반환 하기 때문 입니다.

그러나 합성 된 접근자가 자동으로 이러한 프록시 객체를 반환해야하지 않습니까? 이 문제를 해결하는 적절한 방법은 [super mutableArrayValueForKey...]무엇입니까? 호출하는 사용자 지정 접근자를 작성해야 합니까?


그러나 합성 된 접근자가 자동으로 그러한 프록시 객체를 반환해야하지 않습니까?

아니.

이 문제를 해결하는 적절한 방법은 [super mutableArrayValueForKey...]무엇입니까? 호출하는 사용자 지정 접근자를 작성해야 합니까?

아니요 . 배열 접근 자를 구현합니다 . 이를 호출하면 KVO가 적절한 알림을 자동으로 게시합니다. 따라서해야 할 일은 다음과 같습니다.

[myObject insertObject:newObject inTheArrayAtIndex:[myObject countOfTheArray]];

올바른 일이 자동으로 발생합니다.

편의를 위해 addTheArrayObject:접근자를 작성할 수 있습니다 . 이 접근자는 위에서 설명한 실제 배열 접근 자 중 하나를 호출합니다.

- (void) addTheArrayObject:(NSObject *) newObject {
    [self insertObject:newObject inTheArrayAtIndex:[self countOfTheArray]];
}

(대신 배열의 객체에 대해 적절한 클래스를 채울 수 있고 채워야합니다 NSObject.)

그리고, 대신 [myObject insertObject:…], 당신은 쓰기 [myObject addTheArrayObject:newObject].

슬프게도 add<Key>Object:그 대응 물 remove<Key>Object:은 마지막으로 확인했지만 배열 속성이 아닌 집합 (NSSet에서와 같이) 속성에 대해 KVO에서만 인식되므로 인식하는 접근 자 위에 구현하지 않는 한 무료 KVO 알림을받을 수 없습니다. . 이에 대한 버그를 신고했습니다 : x-radar : // problem / 6407437

나는이 모든 접근 선택기 형식의 목록 내 블로그에 있습니다.


나는 사용하지 것입니다 willChangeValueForKeydidChangeValueForKey이 상황이다. 하나는 대다 관계의 값이 변경되는 것이 아니라 해당 경로의 값이 변경되었음을 나타내는 것입니다. willChange:valuesAtIndexes:forKey:이런 식으로 한 경우 대신 사용하고 싶을 것입니다. 그럼에도 불구하고 이와 같은 수동 KVO 알림을 사용하는 것은 잘못된 캡슐화입니다. 이를 수행하는 더 좋은 방법은 addSomeObject:수동 KVO 알림을 포함하는 배열을 실제로 소유하는 클래스에서 메서드 정의하는 것입니다. 이렇게하면 어레이에 객체를 추가하는 외부 메서드도 어레이 소유자의 KVO를 처리하는 것에 대해 걱정할 필요가 없습니다. 이는 매우 직관적이지 않으며 객체를 추가하기 시작하면 불필요한 코드 및 버그가 발생할 수 있습니다. 여러 곳에서 배열합니다.

이 예에서는 실제로 mutableArrayValueForKey:. 나는 가변 배열에 대해 긍정적 인 것은 아니지만이 방법이 실제로 전체 배열을 새 객체로 대체한다는 문서를 읽었을 때 성능이 문제라면 배열을 소유 한 클래스에서도 구현 insertObject:in<Key>AtIndex:하고 싶을 것입니다. removeObjectFrom<Key>AtIndex:.


변경된 개수를 관찰하려는 경우 집계 키 경로를 사용할 수 있습니다.

[myObj addObserver:self forKeyPath:@"theArray.@count" options:0 context:NULL];

그러나 theArray의 재정렬은 실행되지 않습니다.


자신의 질문에 대한 자신의 대답은 거의 옳습니다. theArray외부 적으로 판매하지 마십시오 . 대신 theMutableArray인스턴스 변수 없음에 해당 하는 다른 속성을 선언하고 다음 접근자를 작성합니다.

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

그 결과 다른 객체가 thisObject.theMutableArray어레이를 변경하는 데 사용할 수 있으며 이러한 변경 사항은 KVO를 트리거합니다.

다른 답변은 구현 insertObject:inTheArrayAtIndex:하고 removeObjectFromTheArrayAtIndex:여전히 정확 하면 효율성이 증가한다는 것을 지적 합니다. 그러나 다른 개체가 이것에 대해 알거나 직접 호출 할 필요는 없습니다.


setter가 필요하지 않은 경우 유사한 성능 ( 내 테스트에서 동일한 성장률 )과 더 적은 상용구 를 갖는 아래의 더 간단한 양식을 사용할 수도 있습니다 .

// Interface
@property (nonatomic, strong, readonly) NSMutableArray *items;

// Implementation
@synthesize items = _items;

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

// Somewhere else
[myObject.items insertObject:@"test"]; // Will result in KVO notifications for key "items"

이는 배열 접근자가 구현되지 않고 키에 대한 setter가없는 mutableArrayValueForKey:경우 이름이 _<key>또는 인 인스턴스 변수를 찾기 때문에 작동합니다 <key>. 하나를 찾으면 프록시는 모든 메시지를이 개체로 전달합니다.

참조 이러한 애플 문서 , # 3, 섹션 "정렬 된 컬렉션에 대한 액세스 용 검색 패턴".


You need to wrap your addObject: call in willChangeValueForKey: and didChangeValueForKey: calls. As far as I know, there's no way for the NSMutableArray you're modifiying to know about any observers watching its owner.


one solution is to use an NSArray and create it from scratch by inserting and removing, like

- (void)addSomeObject:(id)object {
    self.myArray = [self.myArray arrayByAddingObject:object];
}

- (void)removeSomeObject:(id)object {
    NSMutableArray * ma = [self.myArray mutableCopy];
    [ma removeObject:object];
    self.myArray = ma;
}

than you get the KVO and can compare old and new array

NOTE: self.myArray should not be nil, else arrayByAddingObject: results in nil too

Depending on the case, this might be the solution, and as NSArray is only storing pointers, this isn't much an overhead, unless you work with large arrays and frequent operations

참고URL : https://stackoverflow.com/questions/302365/observing-an-nsmutablearray-for-insertion-removal

반응형