2011-12-30 2 views
0

네트워크 호출에서 반환 된 NSData에 NSJSONSerialization을 사용하면 NSDictionaries 및 NSArrays의 중첩 구조가 반환됩니다.중첩 된 NSDictionary 구조 - 트리의 모든 노드의 부모에 대한 참조를 보유하는 방법

이제 트리 구조를 구문 분석하고 추가 사용을 준비하고 싶습니다. 트리의 각 노드는 항상 하위 노드 (NSDictionaries)의 NSArray를 전달합니다. 이 노드들 모두는 하위 노드가 포함 된 NSArray를 포함하는 그것의 부모 노드에 대한 역 참조를 가져야합니다.

이 내가 무슨 말을하고있는 구조의 기본 예입니다

Node { 
nodes:[ 
    node {parent:Node,name:foo}, 
    node {parent:Node,name:bar}, 
    node {parent:Node,name:baz}, 
] 
,name:root} 

각 노드가있는 NSDictionary와 NSDictionaries을 포함하는 각 하위 노드 컬렉션있는 NSArray입니다.

새로운 키 "부모"를 추가하고 그 값을 부모 노드 사전에 설정할 수 없다는 것을 알았습니다. 이것은 객체를 호출 할 때 segfault를 만듭니다. 코드의

기본 예를 들어, 상위 키 생성 :

NSMutableDictionary * foo = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"foo",@"name",[NSNumber numberWithInt:1],@"value",nil]; 
NSMutableDictionary * bar = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"bar",@"name",[NSNumber numberWithInt:2],@"value",nil]; 
NSMutableDictionary * baz = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"baz",@"name",[NSNumber numberWithInt:3],@"value",nil]; 

NSMutableArray *array = [NSMutableArray arrayWithObjects:foo,bar,baz,nil]; 

NSMutableDictionary * container = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"root",@"name",array,@"nodes",nil]; 

[foo setValue:container forKey:@"parent"]; 

NSLog(@"%@",foo); // <-- segfault here 

가 왜 세그먼트 오류를 ​​얻고 있습니까? 노드의 부모 키에있는 역 참조로 인해 구조 설명을 인쇄하는 동안 이것은 무한 루프입니까?

여기이 문제에 대한 다른 접근 방법이 있습니까? 각 키를 가리키는 트리 구조의 외부 표현을 보유해야합니까? 아니면 IS 실제로 부모 노드에 대한 일종의 참조를 저장하는 방법이 있습니까?

미리 감사드립니다.

답변

1

. 세분화 오류가 발생하는 이유는 아마도 NSLog에 무한 루프를 만드는 역 참조 때문일 수 있습니다.

편집 : Google 검색시, NSTreeNode 클래스가있어보다 간단한 작업을 수행해야합니다.

 
@interface MyObjectProxy : NSProxy { 
    id proxied; 
} 

-(id)initWithObject:(id)obj; 

@end 

@implementation MyObjectProxy 

-(id)initWithObject:(id)obj 
{ 
    proxied = obj; 
    return self; 
} 

-(void)forwardInvocation:(NSInvocation*)invocation 
{ 
    [invocation invokeWithTarget:proxied]; 
} 

-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
{ 
    return [[proxied class] instanceMethodSignatureForSelector:selector]; 
} 

-(NSString*)descriptionWithLocale:(id)locale indent:(NSUInteger)level 
{ 
    return [[self class] description]; 
} 

@end 

내가 제대로 NSProxy을 이해한다면 :

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSTreeNode_class/Introduction/Introduction.html

+0

감사! 나는 그 답장을 기대했고, 이제는 내 자신의 모델을 쓸 필요가 있다고 확신한다. 그로 인해 나는 다시 참조 할 수 있습니다. – Nonlinearsound

+0

@Nonlinearsound 안녕하세요. NSTreeNode 클래스를 살펴보십시오. 내가 생각하기에 더 좋아야한다. – MadhavanRP

+0

다시 한번 감사드립니다. iOS 용으로 개발 중이며 불행히도 NSTreeNode는 지원되지 않습니다. 그러나 어쨌든 구조에 대한 아이디어를 얻는 것만으로도 그것을 살펴볼 것입니다. – Nonlinearsound

2

NSLog 줄의 segfault는 무한 루프 때문입니다. NSMutableDictionary를 서브 클래 싱하고 -description을 오버라이드하여 키 "부모"의 값을 출력하지 않도록 할 수 있습니다. 더 일반적으로 NSMutableDictionary는 자체 컨테이너를 포함하도록 설계되지 않았습니다. 하나는 NSDictionary가 자식 객체를 유지하므로 컨테이너가 foo를 유지하고 foo가 컨테이너를 보유하므로 유지 사이클이 생성됩니다.

내 접근 방식은 자신의 모델 클래스를 작성하는 것입니다. NSMutableDictionary 객체를 사용하여 자식 노드를 저장하고 약한 @ property/ivar는 부모 노드에 대한 참조를 보유 할 수 있습니다.

이 그것을 할 수있는 최선의 방법 인 경우에 당신은 내가 확실하지 않다

@interface Node : NSObject { 
    Node    *parent; 
    NSMutableArray *nodes; 
    NSString   *name 
} 
@end 

같은 인터페이스와 여기 간단한 목표 C 클래스를 사용할 수 있지만 NSDictionary을 사용하지 않는 것을 나에게 보인다

+0

감사합니다. Andrew. 나는 당신과 MadhavanRP가 제안한대로 나무에 대한 내 자신의 작은 모델을 작성합니다. 구조체를 사용하기 만하면 NSJSONSerialization이 반환하고 다시 참조하는 기능이 추가되어 확장하기가 너무 쉬웠습니다. – Nonlinearsound

+0

일반적으로 자신의 롤링보다는 내장 클래스를 사용하려고 시도하는 것은 건전한 접근 방식입니다. 그러나 내장 클래스에 제한이있어 문제를 일으키는 경우 자신의 클래스를 작성하는 것을 두려워해서는 안됩니다. 행운을 빕니다! –

0

나는 NSProxy의 인스턴스 내부의 중첩 된 사전을 포장하여 NSDictionaries (순환 그래프)를 포함를 다시 참조에서 중첩 된 NSDictionaries을 방지 제한을 해결 있어요 ,이 메시지는 메시지를 보존하여 다시 참조를 포함하는 중첩 된 사전을 직접 추가 할 때 발생하는 유지주기를 방지합니다. 여하튼, 나는 프록시가 할당 취소된다는 것을 알고있다.

내가 발견 한 세 가지 사소한 문제가 있습니다. 첫 번째는 NSDictionary:descriptionWithLocale:indent:이 전체 구조를 따라 가며 무한 루프가 이미 지적되었음을 나타냅니다. 좋은 소식은 NSProxy에서 "재정의"하면 클래스 클러스터의 일부인 클래스를 재정의하려고 할 때 (NSDictionary처럼) 일반적으로 발생하는 끈적한 상황을 우회한다는 것입니다.

두 번째 문제는 MyObjectProxy:class을 호출하면 NSDictionary 클래스가 아닌 MyObjectProxy 클래스를 반환한다는 것입니다. 제 경우에는 문제가 아니지만 알고 있어야 할 것이 있습니다.

세 번째 문제는 MyObjectProxy이 유지주기를 다시 도입하지 않고도 참조를 유지할 수 없기 때문에 부모 사전에서 하위 사전을 제거하고 부모를 할당 취소하면 해당 MyObjectProxy:proxied이 좀비가됩니다. 다시 말하지만, 제 구조에서 개별 노드를 제거하지는 못하지만, 전체 구조를 불변으로 취급한다는 것을 확실히하는 것은 한계입니다. 제 경우에는 문제가 아닙니다.

+0

나 자신의 클래스를 작성할 필요가없는 것 외에도 중첩 된 NSDictionaries/NSArrays를 사용할 때 장점이 있다는 것을 알아야한다. 주요 이점은 NSDictionary/NSArray가 Key-Value Coding을 준수한다는 점입니다. 일부 개발자는이를 간과한다고 생각합니다. 즉, 예를 들어 주소의 중첩 된 NSArray가있는 회사의 NSDictionary 표현이있는 경우 [myCompanyDict valueforKeyPath : @ "addresses.state"]를 사용하여 상태를 모두 가져올 수 있고 목록을 가져올 수 있습니다 상태를 NSArray로 되돌립니다. – charshep

관련 문제