Pro*_*ber 4 memory-management objective-c ios objective-c-blocks automatic-ref-counting
例如,在ARC下,如果您在self块内部使用,则怀疑块会导致保留周期.
这种解决方法如何防止保留周期?
weakRequest只是指向引用的完全相同对象的指针request.当ARC修改weakRequestor 的保留计数时request,它会影响同一个对象.
然后,在块中,有一个奇怪的事情发生:
__strong ASIHTTPRequest *strongRequest = weakRequest;
Run Code Online (Sandbox Code Playgroud)
这就是说:
ASIHTTPRequest *strongRequest = weakRequest;
[strongRequest retain];
Run Code Online (Sandbox Code Playgroud)
但同样:它是同一个对象.为什么所有这些不同的变量名?他们只是指针!
我从来没有真正关心过块,并试图避免它们.但现在这让我对每个人在谈论"一个块捕获变量"时所说的内容感到好奇.直到今天,我认为这只意味着一个块将保留您使用的每个指针,这些指针已在块的范围之外定义,这意味着该块只保留您在其范围内触摸的任何对象.
我做了这个快速测试:
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];
Run Code Online (Sandbox Code Playgroud)
就像你可以看到对象本身保持完全相同.该块不会创建副本.所以我可以放心地假设C和Objective-C知识的所有年份仍然有效:
ASIHTTPRequest *strongRequest = internetRequest;
ASIHTTPRequest *foo = strongRequest;
ASIHTTPRequest *bar = foo;
if (bar == internetRequest) {
NSLog(@"exact same thing, of course");
}
Run Code Online (Sandbox Code Playgroud)
那么那里发生了什么?如果所有发生的事情都创建了指向同一对象的不同指针,那么如何解决保留计数呢?为什么要创造这些指针?
这不是完全相同的事情吗?
[request setCompletionBlock:^{
NSString *respondeString = [request responseString];
if ([_delegate respondsToSelector:@selector(pingSuccessful:)]) {
[_delegate pingSuccessful:responseString];
}
}];
Run Code Online (Sandbox Code Playgroud)
必须有一些关于Objective-C的秘密,这解释了为什么重复指针解决了内存管理问题.这对我没有任何意义.
它实际上与ARC无关,而是块如何捕获变量.指针是重复的,以便块捕获的变量具有正确的所有权限定符.
weakRequest只是指向请求引用的完全相同对象的指针.当ARC修改weakRequest或request的保留计数时,它会影响同一个对象.
对,它们都指向同一个对象,但weakRequest具有__unsafe_unretained所有权限定符,这意味着当块捕获该变量时,其保留计数不变.
如果request被块捕获,那么它将被保留,并且无论您是否使用ARC,您都将保留周期.
转换回__strong指针只会使该对象在块执行期间保持活动状态.