2013-08-22 2 views
0

내 응용 프로그램이 살아있는 한 필요한 NSMutableArray를 만들고 주 클래스의 @implementation 직후에 suseranArray를 호출 할 수 있습니다. 이 배열은 Vassal이라는 클래스의 여러 객체를 포함합니다. 가신은 단순히 :배열 내의 배열에서 사라지는 항목

1) 인 NSMutableString 2) 또 다른 인 NSMutableString 3) NSMutableArray를 4)

각각의 속국은 또한 응용 프로그램의 수명에 필요한 만든 또 다른 NSMutable 배열, 그들은 결코 변화 .

이러한 개체는 .m 파일에서 합성 된 .h 파일의 (보유) 속성으로 만들어지며 init 함수 중에 개체 Vassal이 만들어 질 때마다 각각 alloc + init이 지정됩니다. 각 하인은 데이터를 채우고 suzerain 배열에 저장합니다. 세 번째 항목은 항상 여러 요소를 가지고 있으며, 버그가 나타난 후에 나는 그것이 비어 있는지 확인하기 위해 줄을 긋지 만 절대로 없으며 생명도 좋습니다.

나중에 특정 Vassal 객체가 필요할 때 우리는 거기에있는 데이터를 가져 오기 위해 3 번째 속성에 액세스하려고 시도합니다. 그리고 때때로 그 배열은 비어 있습니다 ... 나는 그것이 어떻게 든 사라 졌는지 확인하기 위해 검사했습니다. 항상 거기에있는 NSMutableString이 주소 0x2319fb40에 있기 때문에 0x2319f8a0과 같은 멋진 주소를 가지고있는 디버그에는 항상 (두통이 많이 난 후 00000000을 기다리고있었습니다). 무슨 일 이니? 내 머리, 나는 기본적으로 데이터를 보유하고 개체를 다른 개체에 넣어 유지하지만, 배열 안의 데이터가 사라지는 RETAINed 개체를 만드는 중입니다. 가능한 시나리오는 무엇입니까? 시간 :

참고 주셔서 감사합니다 : 마지막 배열은 하나 개의 항목이 결코 누락되지 않도록, 호기심 충분히 개발이 단계에서 하나 개의 항목을 보유하고있는 두 개의 배열에도 불구하고 '형제'

Vassal.h 
@interface Vassal : NSObject 
@property (retain) NSMutableString *wordBody; 
@property (retain) NSMutableString *wordCode; 
@property (retain) NSMutableArray *wordRelations; 
@property (retain) NSMutableArray *wordLinks; 
@end 

Vassal.m 
@implementation Vassal:NSObject 
@synthesize wordBody; 
@synthesize wordCode; 
@synthesize wordRelations; 
@synthesize wordLinks; 
-(NSObject*) init 
{ 
    if(self=[super init]) 
    { 
     wordBody=[[NSMutableString alloc] init]; 
     wordCode=[[NSMutableString alloc] init]; 
     wordRelations=[[NSMutableArray alloc] init]; 
     wordLinks=[[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

//Somewhere in Suseran: 
-(void)fillStuff 
{ 
    ... 
    Vassal *vassal=[Vassal new]; 
    for (int i=0;i<[originalDataString length];i++) 
    { 
     ... 
     [vassal.wordRelations addObject:anItem]; 
     ... 
    } 
    int errorTest=[vassal.wordRelations count]; 
    if (errorTest==0) 
    { 
     //breakpoint here. Program NEVER comes here 
    } 
    [bigArrayOfVassals addObject:vassal]; 
} 
//these arrays are never touched again but here: 
-(void) getVassalstuff:(NSMutableString*)codeOfDesiredVassal 
{ 
    Vassal *aVassal; 
    for (int i=0;i<[bigArrayOfVassals count];i++) 
    { 
      aVassal=bigArrayOfVassals[i]; 
      if ([codeOfDesiredVassal isEqualToString:aVassal.wordCode) 
      { 
        int errorTest=[aVassal.wordRelations count]; 
        if (errorTest==0) 
        { 
         //yay! this breakpoint sometimes is hit, sometimes not, 
         //depending on code's mood. Why is this happening to me? :,(
        } 
      } 
    } 
} 
+1

코드 줄이 설명의 다섯 줄 :-) – dasblinkenlight

+0

"가까운"항목에는 "가까운"주소가있을 것이라고 기대할 이유가 없습니다. 힙은 그렇게 작동하지 않습니다. –

+0

(내 생각 엔 다른 곳에서 그 배열 포인터의 복사본을 가지고 있고 그 포인터 복사본을 통해 배열을 수정하고있다. 포인터 (주소)와 개체 자체 (그 주소의 집) 당신은 주어진 객체에 많은 포인터를 가질 수 있고, 하나를 통해 이루어진 수정은 모두가 볼 수 있습니다.) –

답변

1

변경 가능한 속성 (특정 경우를 제외하고는 그 자체가 나쁜 아이디어 임)을 갖고 있으며이를 보유하고 있음을 확인했습니다.

변경 가능성은 배열을 다른 배열을 기반으로하는 속성으로 설정하고 해당 원래 배열이 변경되면 속성의 배열도 변경된다는 것을 의미합니다. 그것은 수 있으며, 어떤 코드를 표시하지 않았기 때문에 당신이

솔루션 원래의 배열을 비우고, 따라서 속성으로 당신이 가지고있는 배열을 변경하는 것을 모르는 :

내 선호하는 솔루션을 속성에 대해 이러한 클래스의 불변 버전을 사용하는 것입니다. 있는 NSString, NSArray를 대신은 사용 사본 두 번째 솔루션은 가변으로 속성을 떠날하지만 전달 객체의 mutableCopy을 저장하는 그들 각각에 대한 사용자 지정 세터를 작성하는 것입니다

을 유지합니다.

에서 두 경우 모두 속성은 속성을 설정하는 데 사용되는 개체의 복사본이되므로 개체가 클래스 외부에서 변경되면 클래스의 속성에는 영향을주지 않습니다.

단순히 같은 일을 할 것입니다

vassal wordArray = tempArray; 

를 작성 그런

@property (copy) NSArray wordRelations; 

로 속성을 선언하면 코멘트

후, 추가 편집하고 깨끗하고있다 읽을 수있는 ..

+0

모든 것을 시도해 주셔서 고마워요. 초기 값을 채운 후에는 데이터가 변경되지 않습니다. 배열은 채워진 후 변경되지 않는 데이터 파일의 복사본입니다. 사실 나는 배열을 사용하는 대신 파일에서 정보를 읽는 것에 가까운 * * *이되었습니다. '나중에 작동하게 만들고 나중에 최적화하십시오' –

+1

추가 한 후에 변경하지 않는 경우 - 거기에 그 (것)들이 변화 할 수있는 아무 점도 없다. – Abizern

+0

음, wordRelations를 NSArray로 변경했습니다. 지금까지 더 이상 버그가 없습니다. :) 감사합니다. D : (그리고 비슷한 문제로 여기에서 비틀 거리는 여행자를위한 쪽지로서, NSMutableArray * temp를 생성하고 거기에 모든 데이터를로드 한 다음 그 트릭을가 is은 것입니다. wordRelations = [NSArray arrayWithArray : tempArray] 꽤 무차별적인 힘? –