嵌套块中如何保留自身?

3

使用以下代码:

@interface MyClass()
{
   NSMutableArray * dataArray;
}
@end

@implementation MyClass

- (void) doSomething
{
    __typeof__(self) __weak wself = self;
    dispatch_async(dispatch_get_global_queue(0,0), ^{
       __typeof__(self) sself = wself;
       [sself->dataArray addObject: @"Hello World"];

       dispatch_async(dispatch_get_main_queue(), ^{
         [NSThread sleepForTimeInterval: 30];

         UIAlertView *alert = [[UIAlertView alloc] initWithTitle: sself->dataArray[0] 
                                                         message: @"Message"
                                                        delegate: nil
                                               cancelButtonTitle: @"OK"
                                               otherButtonTitles: nil];
         [alert show];
       });
    });
}

@end
  1. 这样从主队列块中访问sself是否正确?
  2. 一旦初始队列完成,sself会失效吗?
  3. 我应该在主队列块内再添加第二个__typeof__(self) sself = wself;吗?

2
顺便提一句,在这个特定的例子中,如果您不想要,就不必做这个 weakSelf/strongSelf 模式。您真正需要做的是在存在潜在强引用循环的情况下。但与您其他的问题不同,这里没有潜在的强引用循环。如果您真的担心对象在代码执行 sleepForTimeInterval 的时候被保留,那么您可以使用 weakSelf/strongSelf 进行操作,但值得注意的是在这种情况下你不必要这样做。 - Rob
2个回答

2
  1. 是的,当然可以。
  2. 不,你可以在main_queue块中使用。
  3. 不需要。即使在global_queue块中,也不需要添加__typeof__(self) sself = wself;;这不是必须的,因为你已经有一个弱化的self对象wself (此外,在块内部的__typeof__(self)部分中,你将保留self)。
  4. 你不需要使用__typeof__。只需使用typeof(self)

1
你问:
这是在主队列块中访问 sself 的正确方法吗?
几乎正确。你还应该检查确保 sself 也不是 nil。这样做是因为对于一个 nil 指针的实例变量进行解引用可能会导致应用程序崩溃。因此,请检查以确保它不是 nil:
- (void) doSomething
{
    typeof(self) __weak wself = self;
    dispatch_async(dispatch_get_global_queue(0,0), ^{
       typeof(self) sself = wself;
       if (sself) {
           [sself->dataArray addObject: @"Hello World"];

           dispatch_async(dispatch_get_main_queue(), ^{
             [NSThread sleepForTimeInterval: 30];

             UIAlertView *alert = [[UIAlertView alloc] initWithTitle: sself->dataArray[0] 
                                                             message: @"Message"
                                                            delegate: nil
                                                   cancelButtonTitle: @"OK"
                                                   otherButtonTitles: nil];
             [alert show];
           });
        }
    });
}

然后你问道:

sself 会在初始队列完成后失效吗?

它会失效,但被内部块保留,并将一直保留到该内部块结束。

我应该在主队列块内添加第二个 __typeof__(self) sself = wself; 吗?

如果你想要的行为是,即使当前对象(可能是视图控制器)被解散,也要看到此警报,则可以这样做(因为你可能希望保留它以便访问 dataArray)。如果你不想再显示警报,则需要重复使用 weakSelf/strongSelf


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接