dispatch_async queue(dispatch_get_main_queue(), ^{}) 内的弱者

weakself inside dispatch_async queue(dispatch_get_main_queue(), ^{})

下面的代码片段在 objective C

__weak MyView *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf.activityIndicatorView stopAnimating];
    [weakSelf.activityIndicatorView removeFromSuperview];
    weakSelf.activityIndicatorView = nil;
});
  1. weakSelf 是否总是 available/valid 因为它在主目录中 队列?
  2. 只有block是other的时候才需要声明strongSelf 比主队列?

您的代码片段太小,无法完整回答您的问题。

  1. weakSelf 可以是 nil 或非零。关键字 weak 表示变量 weakSelf 在某些情况下可以变为 nil。例如,如果您的控制器具有以下 属性:

    @property (retain) MyView* myView;
    

    在某些情况下,您关闭此控制器,然后为 myView:

    调用方法 f
    [self dismissViewControllerAnimated:YES completion:^{
    
        [self.myView f];
    }];
    

    方法的代码 f 基于您在此问题中提供的代码片段:

    -(void)f {
    
        [self removeFromSuperview];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    
            __weak MyView *weakSelf = self;
            dispatch_async(dispatch_get_main_queue(), ^{
    
                [weakSelf.activityIndicatorView stopAnimating];
                [weakSelf.activityIndicatorView removeFromSuperview];
                weakSelf.activityIndicatorView = nil;
            });
        });
    }
    

    我猜你会在调试器中看到当你尝试为 activityIndicatorView 调用 stopAnimatingweakSelf 将是 nil。而且我猜你可以很容易地重现 weakSelf 不会被清除的情况。这意味着你第一个问题的答案是 "No, the weakSelf will be not always available/valid and the main thread does not protect you from nil in this variable"

  2. 如果您不想丢失对块内变量的引用,则需要使用 strongSelf__strong 而不是 __weak)。例如,如果 class MyView 中有一个记录一些调试信息的方法 log

    -(void)log {
    
        NSLog(@"LOG");
    }
    

    如果您想始终在调用代码段中的代码之后记录信息,请使用以下版本的方法 f:

    -(void)f {
    
        [self removeFromSuperview];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    
            __strong MyView *weakSelf = self;
            dispatch_async(dispatch_get_main_queue(), ^{
    
                [weakSelf.activityIndicatorView stopAnimating];
                [weakSelf.activityIndicatorView removeFromSuperview];
                weakSelf.activityIndicatorView = nil;
                [weakSelf log];
            });
        });
    }
    

    所以,你的第二个问题的答案是 "No, you need to use __strong based on your application, the block can be completed in different threads"。