参考自我内部块

jdr*_*drm 3 iphone objective-c ios objective-c-blocks

现在我有一部分代码如下:

__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];
 }];
Run Code Online (Sandbox Code Playgroud)

我主要是这样做的,因为其他一些类继承自此代码所在的类,并实现自己的requestFinished和requestFailed.

如果我将自引用更改为__weak,我会开始收到一些EXC_BAD_ACCESS错误.使用__strong引用一切正常,但我担心创建一个保留周期.请注意,我正在使用ARC.

此代码是否会创建一个会导致问题的保留周期?任何简单的解决方案?我可以遵循任何不同的方法让继承类实现自己的方法来处理响应?

Jod*_*ins 11

是的,它会创建一个保留周期.它会导致问题吗?也许.

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

[operation setCompletionBlockWithSuccess:nil failure:nil];
Run Code Online (Sandbox Code Playgroud)

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

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
});
Run Code Online (Sandbox Code Playgroud)

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

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    { id obj = weakSelf; [weakSelf doSomething]; obj = nil; }
});
Run Code Online (Sandbox Code Playgroud)

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

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
    [weakSelf doSomethingElse];
});
Run Code Online (Sandbox Code Playgroud)

该对象可能在中间doSomething和之间变为零doSomethingElse.

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

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    foo = weakSelf->someIVar; // This can go BOOM!
});
Run Code Online (Sandbox Code Playgroud)

因此,如果您的处理程序正在访问单个消息的弱引用,那么您应该没问题.还有别的东西应该做"弱强舞".

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    MyRequest *strongSelf = weakSelf;
    if (!strongSelf) return;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
    foo = strongSelf->someIVar;
});
Run Code Online (Sandbox Code Playgroud)

如果您认为您遵循这些准则,那么可能是一个更完整的源代码示例,其中包含崩溃详细信息将有助于......

  • 周期在哪里?块保留`self`,`operation`保留块.但是我没有看到"自我保持"操作 (5认同)
  • 使用dispatch_async作为示例具有误导性,因为self没有对其进行强引用,因此不存在保留周期的威胁.或者我不正确理解? (3认同)