2011-03-23 4 views
7

저는 코코아/objective-c에 익숙하지 않습니다. 저는 제 물건들을 풀어 가려고 애 쓰고 있습니다.forin 루프에서 객체를 해제하는 방법은 무엇입니까?

gastroCategoryList = [[NSMutableArray alloc] init]; 
for (NSDictionary *gastrocategory in gastrocategories) { 
    NSString *oid = [gastrocategory objectForKey:@"id"]; 
    GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:@"name"]]; 
    [gastroCategoryList addObject:gc]; 
} 

분석기는 대한에 정의 된 "gastrocategory는"잠재적 메모리 누수입니다 내게 보여줍니다 나는 다음과 같은 코드가 있습니다. 하지만 for 루프의 끝에서 이걸 공개 할 수 있을지 모르겠습니다. 다음 코드에서 또한

:

- (NSArray *)eventsForStage:(int)stageId { 

    NSMutableArray *result = [[NSMutableArray alloc] init]; 

    for (Event *e in eventList) { 
     if ([e stageId] == stageId) { 
      [result addObject:e]; 
     } 
    } 

    return result; 
} 

분석기는 내 "결과가"잠재적 인 누출 것을 알려줍니다. 그러나 나는 이것을 어디에서 풀어야합니까?

@property에서 할당, 복사, 보존 등을 사용해야 할 때를 암기하는 간단한 규칙이 있습니까?

또 다른 문제 :

- (IBAction)showHungryView:(id)sender { 
    GastroCategoriesView *gastroCategoriesView = [[GastroCategoriesView alloc] initWithNibName:@"GastroCategoriesView" bundle:nil]; 

    [gastroCategoriesView setDataManager:dataManager]; 

    UIView *currentView = [self view]; 
    UIView *window = [currentView superview]; 

    UIView *gastroView = [gastroCategoriesView view]; 

    [window addSubview:gastroView]; 

    CGRect pageFrame = currentView.frame; 
    CGFloat pageWidth = pageFrame.size.width; 
    gastroView.frame = CGRectOffset(pageFrame,pageWidth,0); 

    [UIView beginAnimations:nil context:NULL]; 
    currentView.frame = CGRectOffset(pageFrame,-pageWidth,0); 
    gastroView.frame = pageFrame; 
    [UIView commitAnimations]; 

    //[gastroCategoriesView release]; 
} 

가 나는 그것을 얻지 않는다는 "gastroCategoriesView는"잠재적 인 누출이다. 나는 그것을 끝내거나 autorelease로 풀려고했지만 둘 다 잘 동작하지 않습니다. 매번 메소드를 호출하면 앱이 종료됩니다. 대단히 감사합니다! 루프에서

답변

9

, 당신이 당신의 루프 범위에 필요하지 않으므로 더 이상 목록에 추가 한 후 각 gc을 해제 : 당신의 방법에서

gastroCategoryList = [[NSMutableArray alloc] init]; 
for (NSDictionary *gastrocategory in gastrocategories) { 
    NSString *oid = [gastrocategory objectForKey:@"id"]; 
    GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:@"name"]]; 
    [gastroCategoryList addObject:gc]; 
    [gc release]; 
} 

result 선언의 소유권을 면제하는 오토 릴리즈한다 그것은 당신의 방법에서 :

NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease]; 

// An alternative to the above, produces an empty autoreleased array 
NSMutableArray *result = [NSMutableArray array]; 

편집 : 해당 뷰가 윈도우에서 사용하고 있기 때문에 세 번째 문제에, 당신은 당신의 뷰 컨트롤러를 해제 할 수 있습니다. autorelease로 설정하면 동일한 운명이 발생하고 지연 만 발생합니다.

GastroCategoriesView 컨트롤러를 어딘가에 유지해야합니다. 앱 대리인의 인스턴스 변수에

+0

대단히 감사합니다. @property 문제에 대한 규칙도 알고 있습니까? – n3on

+0

@ n3on : 속성이'retain' 또는'copy'라고 선언되면 클래스의'dealloc' 메소드에서 ivar를 해제해야합니다. – BoltClock

+0

@BoltClock : 감사합니다. 그러나 언제 사본을 사용해야합니까? – n3on

1

gastroCategoryList에 추가 된 후 gc를 해제 할 수있는 이유는 개체가 배열에 추가 될 때 배열에 해당 개체가 유지된다는 것입니다. 따라서, 여러분이 여러분의 gc를 릴리즈하더라도 여전히 주위에있을 것입니다; gastroCategoryList에 유지됩니다.

메서드에서 새로 만든 개체를 반환 할 때 autorelease.을 호출해야합니다. 런타임에서 호출 메서드의 범위를 벗어난 후에 만 ​​개체가 해제되므로 호출 메서드에 기회가 주어집니다 반환 값을 가진 무언가.

복사 또는 신규 단어로 시작하는 방법이 있다면 이 아니어야합니다. 개체를 자동으로 꺼내십시오. 호출 메서드를 릴리스하려면이 메서드를 그대로 두어야합니다.

copy와 vs retain은 대개 ... NSArray, NSSet, NSDictionary 및 NSString과 같이 변경 가능한 버전이있는 객체를 복사합니다. 이렇게하면 포인터가있는 객체가 원하지 않을 때 변경할 수 없게됩니다.

그렇지 않으면 개체가 메모리에 남아 있도록 클래스를 유지할 때마다 retain을 사용하십시오.이것은 객체의 부모로 간주되는 객체를 제외하고 거의 모든 객체에 적용됩니다.이 경우 assign을 사용합니다. (보관주기 here에 대한 절 참조).

또한 int와 같은 객체가 아닌 유형에 대해서는 assign을 사용해야합니다.

메모리 Management Programming Guide을 통해 읽습니다. 꽤 도움이됩니다.

3

BoltClock의 답변은 귀하의 질문의 첫 번째 부분에 관한 부분입니다. 나는 나머지 부분을 다루려고 노력할 것이다.

할당은 int, double 또는 struct와 같은 단순한 비 객체 유형을위한 것입니다. "foo = newFoo"와 같이 평범한 이전 과제를 수행하는 setter를 생성합니다. & retain을 복사하면 이름에서 알 수 있듯이 새 값 ("foo = [newFoo copy]")의 사본을 만들거나 보관합니다 ("foo = [newFoo retain]"). 두 경우 모두 setter는 적절하게 이전 값을 해제합니다.

그래서 문제는 복사 할 시점과 보관시기입니다. 대답은 ... 달라집니다. 당신의 수업은 어떻게 새로운 가치를 사용합니까? 다른 코드가 들어오는 객체를 수정하면 클래스가 깨지십니까? 예를 들어, 상상력이 "theString"인 NSString * 속성이 있다고 가정 해보십시오. 다른 코드는 NSMutableString 인스턴스를 theString에 할당 할 수 있습니다. NSString 하위 클래스이기 때문에 합법적입니다. 하지만 그 다른 코드는 가변 문자열 객체에 대한 자체 참조를 유지하고 그 값을 바꿀 수 있습니다 - 코드는 그 가능성을 처리 할 준비가되어 있습니까? 그렇지 않은 경우 자체 코드를 만들어야하며 다른 코드는 변경할 수 없습니다.

한편, 자신의 코드가 theString이 변경되었는지 여부에 대한 가정을하지 않고 그것이 맞는지 여부에 관계없이 작동하는 경우, 불필요하게 만드는 대신 들어오는 객체를 유지함으로써 메모리를 절약 할 수 있습니다 그것의 사본.

기본적으로 불행히도 때로는 간단하지 않은 규칙은 자신의 코드에 자체 복사본이 필요한지 신중하게 생각하거나 다른 코드에서 값이 변경 될 수있는 공유 개체를 올바르게 처리 할 수 ​​있습니다.

+0

개체 유형에 assign을 사용해야하는 경우가 있습니다. 그것은 비 객체 유형을위한 것이 아닙니다. – GendoIkari

+0

True - 사이클, 델리게이트 및 연결된 IBOutlet을 유지합니다. 나는 그것을 단순하게 유지하려고 노력하고 있었지만 조금도 단순화했을지도 모른다. –

+0

나는 항상 IBOutlets를 유지했습니다. 할당해야하는 이유가 있습니까? 자신의 컨트롤러 클래스 이외의 다른 것에 의해 유지됩니까? – GendoIkari

관련 문제