iOS - GCD 和 __strong 参考

iOS - GCD and __strong reference

我有这段代码,我想做的是让自己在将在主线程上执行的块中保持活动状态。结果有点随机,有时会打印 null。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.proArray = [[NSMutableArray alloc]init];

    GCDVC2* __weak weakSelf = self;

    self.postGCDBlock = ^{

        GCDVC2* __strong strongSelf2 = weakSelf;

        [strongSelf2.proArray removeObject:@"3"];
        NSLog(@"%@",strongSelf2.proArray);
        [strongSelf2.activityIndicator stopAnimating];
    };

    self.addObjectsBlock = ^{

        GCDVC2* __strong strongSelf = weakSelf;

        [strongSelf.proArray addObject:@"2"];
        [strongSelf.proArray addObject:@"3"];
        [NSThread sleepForTimeInterval:5];

        dispatch_async(dispatch_get_main_queue(),strongSelf.postGCDBlock);
    };

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), self.addObjectsBlock);

}

这段代码工作正常:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.proArray = [[NSMutableArray alloc]init];

    GCDVC2* __weak weakSelf = self;


    //self.postGCDBlock = ;

    self.addObjectsBlock = ^{

        GCDVC2* __strong strongSelf = weakSelf;

        [strongSelf.proArray addObject:@"2"];
        [strongSelf.proArray addObject:@"3"];
        [NSThread sleepForTimeInterval:5];

         GCDVC2* __weak weakSelf2 = strongSelf;

        dispatch_async(dispatch_get_main_queue(),^{

            GCDVC2* __strong strongSelf = weakSelf2;

            [strongSelf.proArray removeObject:@"3"];
            NSLog(@"%@",strongSelf.proArray);
            [strongSelf.activityIndicator stopAnimating];
        });
    };

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), self.addObjectsBlock);

}

有什么方法可以将第二段代码转换为与第一段代码的结构一起工作吗?我尝试了很多变化,但它总是随机的。我能以某种方式确保 self.postGCDBlock 不会将 self 设为 nil 吗?

更新: 属性声明:

typedef void(^CustomBlock)(void);

@interface GCDVC2 ()
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
@property(nonatomic,strong)NSMutableArray *proArray;
@property (nonatomic, copy) CustomBlock addObjectsBlock;
@property (nonatomic, copy) CustomBlock postGCDBlock;
@end

我认为你的问题在于这一行(我无法用这段代码重现失败案例):

dispatch_async(dispatch_get_main_queue(),strongSelf.postGCDBlock);

此时,在您的 addObjectsBlock 中,strongSelf 持有对 self 的引用,但当您离开该块的范围时,它就会结束。 dispatch_async 将复制 postGCDBlock,但该块没有对 self 的强引用。

要让 dispatch_async 持有对 self 的强引用,您需要这样做:

dispatch_async(dispatch_get_main_queue(), ^{
    strongSelf.postGCDBlock();
});

在块中包装 strongSelf 将导致 dispatch_async 保留 strongSelf(因此 self)足够长的时间以调用 postGCDBlock