KVO 및 ARC 제거 방법


87

ARC 아래의 물체에서 관찰자를 어떻게 제거 합니까? 관찰자를 추가하고 제거하는 것을 잊었습니까? 더 이상 수동으로 메모리를 관리하지 않으면 관찰에서 물러나야할까요?

예를 들어, 뷰 컨트롤러에서 :

[self.view addObserver:self
            forKeyPath:@"self.frame"
               options:NSKeyValueObservingOptionNew 
               context:nil];

이전 removeObserver:에는 뷰 컨트롤러의 dealloc메서드를 호출 했습니다 .


4
KVO .frame에 대해서는 매우 나쁜 생각입니다. StackOverflow에서 Apple 엔지니어가 작성한 것처럼 UIKit의 프레임 속성은 KVO와 호환되지 않습니다. 그것이 작동 할 때, 그것은 순수한 우연 일뿐입니다.
steipete 2011

2
당신의 keyPath @"frame"@"self.frame"아닌가?
Besi 2010-08-10

답변:


126

-dealloc키 값의 관찰을 제거하기에 적절한 장소 인 ARC에서 여전히 구현할 수 있습니다 . [super dealloc]더 이상이 메서드 내에서 호출하지 않습니다 .

-release이전 에 재정의했다면 잘못된 방식으로 일을하고있는 것입니다.


1
이거 확실하니? clang.llvm.org/docs/… , 섹션 7.1.2 에서 인용 합니다. dealloc : "이유 : ARC가 인스턴스 변수를 자동으로 파괴하더라도, 유지 불가능한 자원을 해제하는 것과 같은 dealloc 메소드를 작성해야하는 합법적 인 이유가 있습니다. 이러한 메소드에서 [super dealloc]을 호출하지 못하는 것은 거의 항상 버그입니다."
Elise van Looij

@ElisevanLooij 맞아요. 이 클래스에서 파생 된 경우 [super dealloc]. 누가 당신을 위해 이것을해야 하는가.
Björn Landmesser 2011

@ElisevanLooij 죄송합니다, 음, 전에 확인 했어야 했어요. [super dealloc]dealloc 메서드에서 호출 할 수 없습니다 . 언급 된 클래스를 서브 클래 싱 할 때 이것이 어떻게 작동하는지 알 수 없습니다. 아마 사용하기 단지 것이 좋습니다 finalize(전화 할 경우 대신 [super finalize])
비욘 Landmesser

17
@ElisevanLooij-그들이 만들려고했던 요점은 수동 메모리 관리 사례와 관련이 있습니다. [super dealloc]해당 메서드에서 last를 호출하지 않는 것은 거의 항상 수동 메모리 관리의 버그 이기 때문에 컴파일러가이를 처리하므로 -dealloc더 이상 직접 호출 할 수 없습니다 . -deallocARC 에서 메서드에 넣는 유일한 것은 해제해야하는 비 객체 리소스 또는 관찰자 제거와 같은 정리 작업입니다. 그들이 사용하는 문구는 약간 흐릿하지만 이것이 의미하는 바입니다.
Brad Larson

7
@ BjörnMilcke-Elise의 답변에 대해 언급했듯이 -finalize가비지 컬렉션에서 사용 -dealloc됩니다. 절대 호출되지 않지만이 코드를 -deallocARC 에 배치하는 것은 완벽하게 허용됩니다 . [super dealloc]자동으로 호출되므로 ARC에서 호출하면 오류가 발생합니다.
Brad Larson

1

이 코드로 수행

- (void)dealloc
{
@try{
    [self.uAvatarImage removeObserver:self forKeyPath:@"image" context:nil];
} @catch(id anException) {
    //do nothing, obviously it wasn't attached because an exception was thrown
}
}    

2
에서 예외 처리의 요점은 무엇입니까 dealloc? 그것에 대해 아무것도하기에는 너무 늦었습니다.
Abizern 2014 년

dealloc의 인스턴스 변수에서 관찰자를 제거하는 이유는 무엇입니까? 이 uAvatarImage는 키 경로에 가입 한 관찰자와 함께 곧 할당 해제됩니다.
shoumikhin

1
@shoumikhin 저는 ARC를 사용하고 있으며 dealloc 메서드에서 관찰자를 제거해야했습니다. 나는 당신이 가진 것과 같은 질문이 있습니다. 그러나 클래스의 여러 인스턴스를 실행했을 때 결국 exc_bad_address 오류가 발생했습니다. 이렇게하면 문제가 해결되었습니다. 또한 여기 stackoverflow.com/questions/32490808/… 의 답변 이 문제를 발견하는 데 도움이되었습니다.
mac10688

-2

스택 오버플로의 다른 곳 에서 Chris Hanson은이 목적을 위해 finalize 메서드를 사용하고 소유자가 개체가 완료되었음을 알릴 수 있도록 별도의 무효화 메서드를 구현할 것을 권장합니다. 과거에 저는 Hanson의 솔루션이 잘 고려되어 있다는 것을 알았으므로 그와 함께 할 것입니다.


13
그는 ARC가 아닌 가비지 콜렉션을 언급하고 있다는 점에 유의하십시오 (그의 대답은 2008 년에 작성되었습니다). 가비지 컬렉션에서는 -dealloc호출되지 않습니다. ARC에서는 그렇습니다. -deallocChris Lattner (그가 말하는 내용을 알고있는)가 Apple의 개발자 포럼에서 지적했듯이 에서 KVO 관찰자를 제거하는 것은 완벽하게 허용됩니다 . devforums.apple.com/message/475850
Brad Larson

3
이 모든 일을 해주신 브래드에게 감사합니다. 완료하려면 아니오, 할당을 취소하려면 예, [수퍼 dealloc]은 사용하지 않습니다. 일단 알면 정말 간단합니다. 안녕하세요, @drunknbass, 그 남자의 대답을 받아주세요!
Elise van Looij
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.