2009-12-20 6 views
2

저는 Mac Dev의 초보자입니다. 나는 아이폰 dev에서 왔습니다. 제 질문은 모달이 아닌 창 관리와 관련이 있습니다. 아이폰과는 아주 다르며 메모리 관리 모델이다. 창이기 때문에 넌 모달 윈도우 메모리 관리

-(IBAction)showPreferenceController:(id)sender { 
    if (!preferenceController) { 
    preferenceController = [[PreferenceController alloc]init]; 
    } 
    [preferenceController showWindow:preferenceController]; 
} 

그러나이 코드

는, 윈도우 앱의 수명 동안 메모리에 남아있을 것입니다 : 예를 들어, 내가 환경 설정 창을 말

, 난 창을 보여주기 위해 그런 일을 사용할 수 있습니다 결코 풀려나 지 않았다.

것을 방지하기 위해, 나는 또한 방법은 여기에 설명 사용할 수 있습니다
stackoverflow.com/questions/1391260/who-owns-an-nswindowcontroller-in-standard-practice
PreferenceController+ (id) sharedInstance를 만들고 해제 윈도우 사용 (void)windowWillClose:(NSNotification *)notification

비 모달 윈도우가 공개되지 않는 많은 코코아 코드 샘플을 볼 수 있습니다. 예 : 여기에서 : http://www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/ : 환경 설정 패널 및 모든 하위보기가 awakeFromNib에 생성되므로 모든 앱 수명 동안 메모리에 저장됩니다.

당신은 예를 들어 엑스 코드 앱 걸릴 경우, 비 모달 윈도우의 많은이 있습니다 :
- 글로벌 찾기 창 (CMD + MAJ + F)
- 앱 정보 패널
- 도움말 창
-. ..

가능한 한 메모리를 낮추기 위해 닫을 때이 창을 해제한다고 가정합니다. 코코아 응용 프로그램에서 모달이 아닌 창을 관리하는 가장 좋은 방법을 알고 싶습니다. 기억력을 유지 하시겠습니까? 서둘러 출시 하시겠습니까? 저는 Mac이 iPhone에 비해 많은 메모리를 가지고 있지만, 우리가 사용하지 않는 메모리 객체를 유지하는 것이 좋지 않다고 생각합니다.

감사합니다.

롭 포스트와 편집 :

내가 창으로 -autorelease을 보내고 그래서 나중에 창을 다시 것 nil을 내 포인터를 설정합니다. 이는 컨트롤러에 + sharedController를 사용할지 여부와 관련이 없지만 인용하는 기술과 유사합니다. 공유 컨트롤러가 있는지 여부에 관계없이이 작업을 수행 할 수 있습니다.

싱글 톤 (+ sharedController)이 없으면 그렇게하는 방법이 없습니다.
나는이 예제 무슨 뜻인지 설명 : 응용 프로그램 컨트롤러에서
:

@interface AppController : NSObject <NSApplicationDelegate> { 

구현 :

@interface PreferenceController : NSWindowController <NSWindowDelegate> 

구현 :

환경 설정 컨트롤러에서

-(IBAction)showPreferenceController:(id)sender { 
    if (!preferenceController) { 
    preferenceController = [[PreferenceController alloc]init]; 
    } 
    [preferenceController showWindow:preferenceController]; 
} 

- (void)windowWillClose:(NSNotification *)notification { 
    [self autorelease];self=nil; 
} 

창이 닫히고 다시 열면 충돌이 발생합니다. preferenceController가 해제되었지만 nil과 같지 않습니다. 그래서 창이 닫힐 때 preferenceController를 nil로 설정해야합니다. 싱글 톤으로는 아무런 문제가 없습니다.
싱글 톤이 없으면 appController를 Preference Window의 델리게이트로 설정하여 윈도우가 닫힐 때 preferenceController를 nil로 설정할 수 있습니다. 하지만 나는 그런 식으로하지 않습니다. 프레스톤과 편집


내가 그것을 말하지 않았다 코멘트 그러나 나는 우리가 -(IBAction)showPreferenceController:(id)sender 여러 번 호출해도 내 비 모달 창 하나 개의 인스턴스 만합니다.
그 이유는 preferenceController가 nil과 같거나 appController가 아닌지 테스트하기 때문입니다.
그래서 창을 닫으면 appController에서 preferenceController를 nil로 설정해야합니다.
그래서 해결책은 다음과 같습니다
의 AppController에서 는 NSWindowWillCloseNotification을 듣고 :

- (void)windowWillClose:(NSNotification *)notification { 
    if ([notification object] == [preferenceController window]) { 
     [preferenceController autorelease]; 
     preferenceController = nil; 
    } 
} 

이 맞습니까? 이것이 유일한 해결책입니까? 모달이 아닌 창을 관리하는 것이 조금 복잡해 보입니다 ...

+1

여기에 '자기'를 공개해서는 안됩니다 (거의 자동으로 [자기 배포]라고 부르면 안됩니다). self.window를 해제하고 self.window = nil로 설정해야합니다. –

+1

또한, 나는 이것을 권장합니다. [self.window autorelease]; self.window = nil; ' 그렇게하면 창은 실제로 해제되기 전에 닫을 수 있습니다. –

+0

고마워요 롭, 내 예제는 말했듯이 예제가 충돌하기 때문에 문제를 설명하기 만하면됩니다. preferenceController를 nil로 설정하고 appController에서 구현해야합니다. 마지막 질문에 대한 질문을 편집했습니다. – Benoit

답변

3

여기 모든 올바른 방법으로 생각하고 있습니다. 네가 그걸 많이 가지고 있기 때문에 메모리를 누설하는 것은 좋지 않다. 즉, Mac에서 닫히기 때문에 창을 놓지 않는 것이 일반적입니다. 일반적으로 재로드 비용을 피하기 위해 다시 열 예정이라고 생각하면 잠깐 기다려야합니다.

NSWindow에는 소유와 소유권자에 관한 두 개의 학교가 있습니다. 나는 "소유"학교 다. 필자는 일반적으로 모든 윈도우에 ivar을 유지하고 적절할 때 그것을 해제하는 소유자에게 제공합니다. 일반적으로 그것이 대리인이며 때로는 앱 컨트롤러입니다. -windowShouldClose:에서는 나중에 창을 다시 만들려고 창에 -autorelease을 보내고 내 포인터를 nil로 설정합니다. 이것은 컨트롤러에 대해 +sharedController을 사용할 지 여부와 관계없이 인용하는 기술과 유사합니다. 공유 컨트롤러가 있는지 여부에 관계없이이 작업을 수행 할 수 있습니다.

소유주가없는 학교는 NSWindow의 -setReleasedWhenClosed:을 사용하여 자동으로 닫힐 때 자동으로 해제됩니다. 나는 위임자가 없을 수도 있기 때문에 당신이 참조하는 여러 윈도우가 시스템에 의해 제공 될 때이 방법으로 그렇게한다고 믿습니다. 이는 특정 종류의 패널에서 유용 할 수 있지만 일반적인 패턴으로주의해야합니다. 거의 모든 경우에 명시적인 메모리 관리를하는 것이 좋습니다.

+0

롭, 고맙습니다. 창문망을 더 잘 이해합니다. 내가 싱글 톤 개체없이 창을 해제하는 방법을 이해하지 못하기 때문에 귀하의 게시물에 따라 내 질문을 편집했습니다. – Benoit

1

Interface Builder에서 창에 대해 "릴리스 할 때 릴리스"를 선택하거나 프로그래밍 방식으로 설정하면 인터페이스가 자동으로 해제됩니다.또한 윈도우의 델리게이트가 windowShouldClose : delegate 메소드에서 윈도우를 자동으로 가져 오도록 할 수 있습니다.

창이 닫힐 때 창 컨트롤러를 해제하려면 창 컨트롤러가 해당 창에서 NSWindowWillCloseNotification을 수신 대기하고 해당 메서드에서 [자동으로 실행]을 수행하게하십시오. 나는 싱글 렛 (singleton) 환경 설정 컨트롤러를 만드는 팬이 아니며, 실제로 사용자는 거의 상호 작용하지 않는다.

+1

감사합니다. Xcode 도움말에서 setReleasedWhenClosed에 대해 "닫을 때 해제"는 윈도우 콘트롤러가 소유 한 윈도우에서는 무시됩니다. " 그게 내 사건이야. 내 질문에, 나는 "windowWillClose"autorelease 예제를 넣어. 하지만 문제는 이것입니다. 창을 여러 번 호출한다고해도 하나의 창만 원합니다. 그래서 "showsPreferenceController"메서드에서 preferencesController가 nil인지 아닌지를 테스트합니다. 그래서, 창이 닫힐 때 preferenceController를 nil로 설정해야합니다. 그런 다음 NSWindowWillCloseNotification을 appController에서 듣고 PreferencesController에서 듣지 않아야합니다. 사실인가요? – Benoit

+0

최상의 솔루션을 찾으려면 귀하의 의견에 나의 질문을 편집했습니다. – Benoit

+0

아, 그 창 릴리스 동작에 대해 정확합니다. 나는 글로벌 인스턴스 객체를 언급하고 있었고, 일반적인 인스턴스 변수는 언급하지 않았다. 일단 할당되면, 싱글 톤 객체는 앱이 종료 될 때까지 해제되지 않습니다. 예, 환경 설정 컨트롤러를 소유 한 객체에서 창 닫기 알림을 수신하고 인스턴스 환경 변수 컨트롤러를 자동으로 해제 한 다음 인스턴스 변수를 nil로 설정할 수 있습니다. 환경 설정 컨트롤러는 자신이 소유 한 창을 해제합니다. 이 일의 메모리 사용량이 당신에게 큰 걱정거리라면, 그렇게 할 수 있습니다. –