关于iphone:参考自我内部块

Reference to self inside block

现在我有一部分这样的代码:

1
2
3
4
5
6
7
8
9
__strong MyRequest *this = self;

 MyHTTPRequestOperation *operation = [[MyHTTPRequestOperation alloc]initWithRequest:urlRequest];
 [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *request, id responseObject) {
     [this requestFinished:request];
 }
 failure:^(AFHTTPRequestOperation *request, NSError *error) {
     [this requestFailed:request withError:error];
 }];

我之所以这样做,主要是因为其他一些类继承了代码所在的类,并实现了它们自己的requestFinished和requestFailed。

如果我将自引用改为"弱",我就会出现一些exc-bad访问错误。有了一个强大的参考,一切都很好,但我担心创建一个保留周期。请注意,我使用的是ARC。

此代码是否创建了会导致问题的保留周期?有什么简单的解决办法吗?我可以采用任何不同的方法来让继承类实现它们自己的方法来处理响应?


是的,它创建了一个保留周期。它会引起问题吗?也许吧。

如果API支持,您可以重置处理程序,这将手动中断保留周期:

1
[operation setCompletionBlockWithSuccess:nil failure:nil];

或者可以使用弱引用。但是,你说你尝试了一个弱引用,它崩溃了。弱引用在消息开始时保证为零,或者在消息处理之前保持有效。换句话说,考虑…

1
2
3
4
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
});

如果异步块执行时weakSelf为零,则"无"发生。如果不为零,则保证至少保留到doSomething完成。实际上,它类似于:

1
2
3
4
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    { id obj = weakSelf; [weakSelf doSomething]; obj = nil; }
});

但是,请注意,如果您这样做:

1
2
3
4
5
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
    [weakSelf doSomethingElse];
});

doSomethingdoSomethingElse之间,目标可能变为零。

此外,如果您通过弱引用访问一个实例变量,您只需要一个SEGV:

1
2
3
4
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    foo = weakSelf->someIVar; // This can go BOOM!
});

因此,如果您的处理程序正在访问单个消息的弱引用,那么您应该很好。还有什么可以跳"弱而有力的舞蹈"。

1
2
3
4
5
6
7
8
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    MyRequest *strongSelf = weakSelf;
    if (!strongSelf) return;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
    foo = strongSelf->someIVar;
});

如果您认为您遵循的是指导原则,那么一个更完整的源代码示例,以及崩溃详细信息将有助于…