Objective-C/Cocoa 키-값 코딩 및 배열에서
-
20-08-2019 - |
문제
iPhone 앱을위한 키 값 코딩으로 배열을 채우는 "올바른"방법을 해결하려고합니다. 나는 작동하는 무언가를 생각해 냈지만 상당히 해킹됩니다. 기본적으로 XML 문서를 코드 생성 모델 세트로 구문 분석하고 있습니다. XML 이이 형식이라고 가정 해 봅시다.
<foo>
<bar>
<item name="baz" />
<item name="bog" />
</bar>
</foo>
막대 요소를 나타내는 생성 된 객체에는 하위 노드에 대해 NSMutableARRAY가 정의되어 있습니다.
@interface Bar : NSObject {
NSMutableArray *item;
}
@end
따라서 기본적으로 setValue : forkey : bar 인스턴스에서 항목 객체의 단일 인스턴스로 nsmutablearray 인스턴스를 덮어 쓰는 경우가 있습니다. 내가이 일을하기 위해 현재 한 일은 그것이 해킹되는 곳입니다. 나는 배열 인스턴스 변수의 이름을 다른 것으로 바꾸었다.
@interface Bar : NSObject {
NSMutableArray *items;
}
@end
이로 인해 SetValue : Forkey : Miss의 기본 액세서가 발생합니다. 그런 다음이 메소드가 BAR 구현에 추가했습니다.
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
if([key isEqualToString:@"item"]) {
if(items == nil) {
items = [[NSMutableArray alloc] init];
[items retain];
}
[items addObject:value];
}
}
그리고 모든 것이 작동합니다! 그래도 더 나은 방법이 있어야한다고 확신합니다! 키 값 코딩 프로그래밍 안내서를 읽었지만 배열 액세서에게 어떻게 작동 해야하는지에 대해서는 불분명하기 때문에 무언가를 놓치고 있어야합니다. Countof : 및 Objectinatindex를 구현하려고 시도했습니다. KVC 프로그래밍 안내서가 표시되는 것처럼 보이지만 여전히 NSMutableAreRay가 항목 유형의 인스턴스로 덮어 쓰고 있습니다.
해결책
배열에 KVC 속성을 사용하려면 설명서를 살펴보아야합니다. mutableArrayValueForKey:
기본적으로 수업과 함께 :
@interface Bar : NSObject {
NSMutableArray *items;
}
@end
다른 곳에서 배열을 초기화했다고 가정하면 이러한 방법을 최소로 정의합니다.
- (void)insertObject:(id)object inItemsAtIndex:(NSUInteger)index {
[items insertObject:object atIndex:index];
}
- (void)removeObjectFromItemsAtIndex:(NSUInteger)index {
[items removeObjectAtIndex:index];
}
- (NSArray *)items {
/* depending on how pedantic you want to be
possibly return [NSArray arrayWithArray:items] */
return items;
}
해당 메소드를 구현하면 호출 할 수 있습니다 [bar mutableArrayValueForKey:@"items"]
. 반환합니다 NSMutableArray
객체를 추가하고 제거 할 수있는 프록시 객체. 해당 개체는 적절한 KVO 메시지를 생성하고 방금 정의한 메소드를 사용하여 실제 배열과 상호 작용합니다.
다른 팁
Martin이 제안한 것처럼 항목이 추가되거나 제거 될 때 배열을 직접 관찰 할 수 없습니다. 대신, 이것은 막대 객체의 "to-many"속성으로 간주되며 KVO 주장을 직접 만드는 것을 다루어야합니다. 막대에서 품목을 추가하고 제거하기 위해 이와 같은 일을 할 수 있습니다.
@interface Bar : NSObject
{
NSMutableArray *items;
}
-(void)addItem:(id)item;
-(void)removeItem:(id)item;
@end
@implementation Bar
-(id)init
{
if( (self = [super init]) ) {
items = [[NSMutableArray alloc] init];
}
return self;
}
-(void)addItem:(id)item
{
NSParameterAssert(item);
NSIndexSet *iset = [NSIndexSet indexSetWithIndex:[items count]];
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:iset forKey:@"items"];
[items addObject:item];
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:iset forKey:@"items"];
}
-(void)removeItem:(id)item
{
NSParameterAssert(item);
NSIndexSet *iset = [NSIndexSet indexSetWithIndex:[items indexForObject:item]];
[self willChange:NSKeyValueChangeRemoval valuesAtIndexes:iset forKey:@"items"];
[items removeObject:item];
[self didChange:NSKeyValueChangeRemoval valuesAtIndexes:iset forKey:@"items"];
}
@end
항목을 직접 설정/교체 할 수 있기를 원한다면 직접 할 수있는 방법을 제시해야합니다. 일반적으로 나는 제안하고 NSArrayController
이런 종류의 경우 iPhone을 사용하기 때문에 기본적 으로이 기능을 직접 만들어야합니다.
글쎄, 당신이 그것에 대해 갈 수있는 두 가지 방법이 있습니다.
- 항목을 전달하는 바 클래스에 "항목 추가"메소드 추가
- KVC를 수행 할 때 전체 항목을 통과하는지 확인하십시오.
KVC를 사용하여 배열에 항목을 추가 할 수있는 방법이 없다고 생각합니다.
전화하기에 충분합니다 valueForKey:@"item"
그리고 결과는 변이 가능합니다. 그래서 당신은 다음을 말할 수 있습니다.
NSMutableArray* m = [theBar valueForKey:@"item"];
[item addObject: value];
정면을 구현하지 않는 한 다른 방법이 필요하지 않습니다 (변수 인스턴스 변수가없는 키).