为什么复制指针以解决ARC下基于块的保留周期是有意义的?

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的秘密,这解释了为什么重复指针解决了内存管​​理问题.这对我没有任何意义.

Dar*_*ren 6

它实际上与ARC无关,而是块如何捕获变量.指针是重复的,以便块捕获的变量具有正确的所有权限定符.

weakRequest只是指向请求引用的完全相同对象的指针.当ARC修改weakRequest或request的保留计数时,它会影响同一个对象.

对,它们都指向同一个对象,但weakRequest具有__unsafe_unretained所有权限定符,这意味着当块捕获该变量时,其保留计数不变.

如果request被块捕获,那么它将被保留,并且无论您是否使用ARC,您都将保留周期.

转换回__strong指针只会使该对象在块执行期间保持活动状态.