ARC에서 블록 내부에 self
을 사용하는 경우 블록에 유지주기가 발생하는 것으로 의심됩니다.ARC에서 블록 기반 유지주기를 해결하기 위해 포인터를 복제하는 것이 왜 의미가 있습니까?
나는이처럼 workaround here을 본 적이 :
방법이 해결 방법은 사이클을 유지 방지 할 수 있습니까?
weakRequest
은 request
에 의해 참조되는 똑같은 개체에 대한 포인터입니다. ARC가 보유 수를 weakRequest
또는 request
으로 수정하면 동일한 개체에 영향을줍니다. 말에
__strong ASIHTTPRequest *strongRequest = weakRequest;
이것은 eqivalent입니다 :
ASIHTTPRequest *strongRequest = weakRequest;
[strongRequest retain];
그러나 다시 :
그런 다음 블록에, 무슨 이상한 것이 있습니다 그것은 하나의 동일한 개체입니다. 왜 이러한 모든 변수 이름을 사용합니까? 그들은 단지 포인터 일뿐입니다!
저는 블록에 대해별로 신경 쓰지 않았고 피하려고했습니다. 그러나 이제는 이것이 내가 블록이 변수를 포착한다고 말할 때 모두가 말하는 것에 대해 호기심을 샀다. 오늘까지는 이것이 단지 블록이 여러분이 사용하는 모든 포인터를 블록의 범위 밖에서 정의했음을 의미한다고 생각했습니다. 즉, 블록이 범위 내에있는 객체를 그대로 유지한다는 것을 의미합니다. 당신이 개체 자체가 정확히 동일하게 유지 볼 수 있습니다처럼
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:v];
v.backgroundColor = [UIColor orangeColor];
NSLog(@"self = %p", self); // 0x6a12a40
[UIView animateWithDuration:1.5
delay:0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
UIViewController *my = self;
NSLog(@"my = %p", my); // 0x6a12a40
v.frame = CGRectMake(200, 200, 100, 100);
}
completion:nil];
:
나는이 빠른 테스트를했다. 블록은 사본을 작성하지 않습니다. 그래서 저는 C와 Objective-C에 대한 지식이 여전히 유효하다고 가정 할 수 있습니다 :ASIHTTPRequest *strongRequest = internetRequest;
ASIHTTPRequest *foo = strongRequest;
ASIHTTPRequest *bar = foo;
if (bar == internetRequest) {
NSLog(@"exact same thing, of course");
}
그래서 어떻게 될까요? 어떻게하면 동일한 객체에 대해 다른 포인터를 만드는 경우에이 방법으로 유지 카운트를 해결할 수 있습니까? 왜 그 포인터를 만드는 여분의 마일?
완전히 똑같지 않습니까?
[request setCompletionBlock:^{
NSString *respondeString = [request responseString];
if ([_delegate respondsToSelector:@selector(pingSuccessful:)]) {
[_delegate pingSuccessful:responseString];
}
}];
여기서 포인터를 복제하면 메모리 관리 문제가 해결되는 이유를 설명하는 Objective-C에 대한 몇 가지 비밀이 있어야합니다. 그것은 나에게 어떤 의미가 없습니다.
내가 틀릴 수도 있지만 블록 내에서 __strong 포인터가 블록 기간 동안 계속 유지한다고 생각하지 않습니다. ARC가이를 수행 할 수있는 유일한 방법은 객체를 유지하는 것입니다. ARC가 블록의 수명을 알 수 없기 때문에 (특히 나중에 실행을 위해 저장 될 가능성이 높습니다) 유지 사이클을 생성합니다.그것이 블록을 유지한다면 (그렇다고 생각하지 않습니다), 블록 내부에 __strong 변수를 추가하면 블록 외부의 __weak 변수의 목적이 완전히 상실됩니다. –
위대한 설명! @ 아론, 나는 유지 사이클의 문제는 당신이 블록을 만들고 그것을 오랫동안 사용하지 않는다면, 블록이 실행되어 그 객체를 놓을 때까지 보존 된 객체가 사라지지 않을 수도 있다는 것입니다. 이 경우에는 이제 나에게 맞는 말이있다. 요청 객체는 블록이 시작될 때 * 블록 안에 유지되고 그 후에는 해제되고 유지 사이클이 끊어진다. 물론 이것은 블록이 지연과 함께 실행되면 블록이 실행되기 전에 요청 객체가 할당 해제 될 가능성을 열어줍니다. 권리? –
__weak 참조를 사용하는 주요 이유는 나중에 실행할 블록을 저장하기 때문입니다. 블록을 가져 오는 사용자 지정 컨트롤이 있고 그 블록을 iVar로 저장합니다. 이러한 컨트롤은 일반적으로 블록을 제공하는 개체에 의해 유지되므로 블록이 해당 개체를 보유하고 있으면 보유주기가 유지됩니다 ... 또한 블록 내에 인스턴스화 된 변수가 해당 개체를 보유하면 다시 보유주기가 유지됩니다 그 변수가 존재합니다. 이것은 왜 __weak var에 전달 된 __strong var을 할당하면 객체의 보유 개수를 증가시키지 않으므로 아무 것도하지 않는다고 생각하는 이유입니다. –