块和异步回调,释放对象-需要将块设为零

ban*_*isa 3 asynchronous block objective-c dealloc nszombie

这里有一个类似的问题,并不能完全解释我想要什么:Objective C Blocks as Async-callbacks&BAD ACCESS

我有一个视图控制器,它使用异步回调调用服务。回调使用一个块来完成,该块引用视图控制器上的变量以填充它们。

看起来像这样:

- (void) loadData {
    __block MyViewController *me = self;
    [self.service executeWithCompletion:^(NSArray *result, NSError *error) {
        if (!error) {
            me.data = result;  
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我取消分配视图控制器,则回调将严重访问“ me”。

使“ me”为NULL的最简单方法是什么?如果我将其作为iVar,那么它会带回循环引用...我认为呢?

我想我缺少明显的东西。

谢谢

Lil*_*ard 5

您是否定位到iOS 5.0或更高版本(或Mac OS X 10.7或更高版本)?如果是这样,则可以使用ARC和一个__weak变量(而不是__block一个)。当释放所引用的对象时,它将自动归零。您的代码看起来像

- (void)loadData {
    __weak MyViewController *me = self;
    [self.service executeWithCompletion:^(NSArray *result, NSError *error) {
        if (!error) {
            MyViewController *strongMe = me; // load __weak var into strong
            if (strongMe) {
                strongMe.data = result;
            }
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

如果您需要对较旧操作系统的支持,则需要找到其他解决方案。一种解决方案是继续进行下去,让块保留下来self。如果保证该服务执行完成块(然后释放它),则这只会产生一个临时循环,该循环将在运行完成块时自动中断。另外,如果您有某种取消服务的方法(以确保取消后无法调用该块的方式),则可以坚持使用__block并且只需确保在中取消该服务-dealloc。也有其他选择,但它们更复杂。