2012-09-10 3 views
3

블록이 강력한 참조를 만들고 (따라서 참조 카운트가 증가하지 않는) 블록 내에서 '자체'(및 ivars)를 참조하는 올바른 방법은 무엇입니까?자기 참조와 인스턴스 vars를 참조하는 블록

__weak WhateverController *weakSelf = self; 
^(id sender) { 
    [weakSelf.navigationController popViewControllerAnimated:YES]; 
}; 
:

위를 회피하기 위해
^(id sender) { 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

, 나는 다음을 해왔습니다 : 예를 들어

, 나는 다음과 같은 발견했습니다는 '자기'에 대한 심판이 카운트를 증가

그리고 네, 이것이 의사 코드라는 것을 알고 있습니다.

답변

10

또한, 자기에 대한 간접 참조도 자기에 유지 만든다. 예를 들어 _ivar이 인스턴스 변수 인 경우이를 액세스하는 것은 self에 대한 암시 적 참조이므로 다음도 자체를 유지합니다. 당신의 weak 예에 확장 또한

^(id sender) { 
    [_ivar popViewControllerAnimated:YES]; 
} 

, 약한 참조로 메시지를 보낼 OK입니다. 그것이 없다면 아무 일도 일어나지 않을 것입니다. 그렇지 않으면 컴파일러는 메소드 호출을 통해 참조가 유효하게 유지되도록하는 코드를 생성합니다.

그래서,이 괜찮 : 푸 nil가되거나하지 않을 경우,이 doSomething의 실행을 통해 nil이 아닌 남아 보장

__weak Foo *weakSelf = self; 
^(id sender) { 
    [weakSelf.foo doSomething]; 
} 

때문이다. 이 경우

__weak Foo *weakSelf = self; 
^(id sender) { 
    [weakSelf.foo doSomething]; 
    [weakSelf.foo doSomethingElse]; 
} 

, 당신은 아마 당신의 자신의 강한 참조를 만들 : 당신이 원하는 아마 아니다 호출 사이에-selfnil에 갈 수 있기 때문에

그러나, 다음은 권할 것 블록 내부에서 일관된 값을 갖게됩니다. 직접 약한 참조를 통해 인스턴스 변수에 액세스하는 경우 반면에

, 당신은 이 코드 때문에 약한 강한 춤을 수행해야합니다 weakSelfnil 경우

__weak Foo *weakSelf = self; 
^(id sender) { 
    weakSelf->_foo = bar; 
} 

는 날려 버리겠다.

따라서, 위의 마지막 두 상황에서, 당신은 같은 것을하고 싶지 : 물론

__weak Foo *weakSelf = self; 
^(id sender) { 
    Foo *strongSelf = weakSelf; 
    if (!strongSelf) return; 
    // Now, do anything with strongSelf, as it is guaranteed to be around 
} 

를 실제로 직접 인스턴스 변수에 액세스하는 경우 IVAR 상황

+1

에서 ... 단지 문제 두 번째 예를 들어, 나는'[weakSelf.foo doSomething]; [weakSelf.foo doSomethingElse]; ' –

+0

@ChristopherPickslay - 참으로. 감사! –

2

애플의 표기법은 그 자체가 아니지만 괜찮습니다. 비 아크 프로젝트에서
블록에 의해 유지되는 '자기'을 방지하기 위해 다음 코드를 사용
__block id sself = self

관련 문제