self
,就会怀疑一个块引起了循环引用。我看到了一个解决方法(在此处),像这样: 这个解决方法如何防止循环引用?
weakRequest
只是指向由request
引用的确切相同对象的指针。当ARC修改weakRequest
或request
的保留计数时,它影响的是同一个对象。然后,在块中,有这样奇怪的事情发生:
__strong ASIHTTPRequest *strongRequest = weakRequest;
这相当于说:
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,可能有一些秘密可以解释为什么在这里复制指针可以解决内存管理问题。但对我来说,这根本就没有任何意义。