1
ARC가 설정된 코코아 코드에서 아래의 창 닫기 이벤트를 관찰하려고했습니다. addObserverForName 및 옵저버 삭제
ScanWindowController * c = [[ScanWindowController alloc] initWithWindowNibName:@"ScanWindowController"];
[scanWindowControllers addObject:c];
[c showWindow:nil];
NSMutableArray *observer = [[NSMutableArray alloc] init];
observer[0] = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[scanWindowControllers removeObject:c];
[[NSNotificationCenter defaultCenter] removeObserver:observer[0]];
}];
제가 이 창을 닫은 후 상기 제어부 (C)에 대한 모든 참조를 제거 생각. 사실,이 코드는 Window를 닫은 후에 ScanWindowController를 dealloc하지 않습니다. 컨트롤러에 약한 참조를 사용하여 아래와 같이 작성하면 ScanWindowController의 dealloc이 호출됩니다.
ScanWindowController * c = [[ScanWindowController alloc] initWithWindowNibName:@"ScanWindowController"];
[scanWindowControllers addObject:c];
[c showWindow:nil];
__weak ScanWindowController * weak_c = c;
NSMutableArray *observer = [[NSMutableArray alloc] init];
observer[0] = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[scanWindowControllers removeObject:weak_c];
[[NSNotificationCenter defaultCenter] removeObserver:observer[0]];
}];
왜 첫 번째 코드가 작동하지 않습니까?
** observer **는 지역 변수이며 ARC가 사용됩니다. 따라서 함수의 끝에서 ** observer ** 배열과 내용이 릴리즈되어야합니까? –
ARC는 ** 해당 지역이 범위를 벗어날 때 지역 변수가 참조하는 객체가 파괴되지 않도록 ** 보장하지 않습니다 **. * 참조 중 하나가 해제되지만 객체가 할당 취소 된 것은 아닙니다. 블록은 다른 참조를 보유하고 있으며 관찰 객체 ('-addObserverForName : object : queue : usingBlock :'에 의해 반환 된 객체)가 존재하는 한 블록은 유지됩니다. 이 관찰 객체는 '관찰자'배열이 존재하는 한 존재합니다. 이것은 보존주기입니다. –
아, 알 겠어! 그래서, ** arr = @ []; arr [0] = arr; **과 같이 썼습니다. 블록 끝에서 ** [observer removeAllObjects] **를 호출하면 참조 루프가 해결되었습니다. 감사 ! –