ios - Objective-C 中一个奇怪的 block 问题

标签 ios objective-c objective-c-blocks

我有一个 AuthService 类,它有一个执行异步连接登录的方法。该类实现了 NSURLConnectionDataDelegate 协议(protocol),以便当服务器响应时,它会调用之前由 View Controller 设置的完成处理程序来更新 UI。

这是完成处理程序的定义

@property void (^completionHandler)(LoginResult *result);

这是类接收服务器响应的时间

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSString *response = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];

    //Do something with the response and create an instance of LoginResult class

    self.completionHandler(loginResult);
}

如果完成处理程序 block 只是调用 NSLog 来写入控制台作为参数传递的登录结果信息,那么它会完美运行,不会出现错误。但是当我想调用拥有该 block 的 ViewController 的方法时,就会发生一些奇怪的事情。

我知道当您将一个对象包含在拥有该 block 的 block 中时,会存在一个保留周期。这就是我编码的方式。

__block typeof(self) bself = self;

[authService login:blablabla completionHandler:^(LoginResult *result) {
    [bself didReceiveLoginResult:result];
}

我认为这将防止陷入保留周期。但调试时出现“Thread: EXC_BAD_ACESS”错误。

附注 例如,即使该属性未声明为“复制”,以下代码也可以完美运行

[authService login:blablabla completionHandler:^(LoginResult *result) {
    NSLog(@"Login %@", result.success ? @"success" : @"failed");
}

最佳答案

该属性应声明为copy,否则该 block 将保留在堆栈上,并且在您调用它时可能已经被释放。

此外,还有一些简单的方法可以防止出现保留圈。使用完后只需释放该 block 即可,例如

self.completionHandler(loginResult);
self.completionHandler = nil;

不需要使用 __block 巧妙的魔法。当保留周期是临时的时,是允许的。

编辑:

如果 block 中没有对 self 的引用,编译器会将其设为全局 block ,并且永远不会被释放。请参阅http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

关于ios - Objective-C 中一个奇怪的 block 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16623846/

相关文章:

ios - iOS 10 GameCenter 基于 iMessaged 的​​邀请

objective-c - 如何使 ZBarReaderViewController 全屏

objective-c - 为什么这个从 NSData 对象创建的 NSString 无法显示它有内容?

ios - NSUserDefaults setObject :nil vs. setNilValueForKey

ios - xcode 保留周期警告仅有时发生

ios - Objective-C block : How to set an object to nil which uses block-based callback mechanism?

iOS: block 复制并添加到可变数组,清空数组时是否需要释放它们?

ios - 收到此警告初始化类型为 'id' 的指针

ios - 如何使用 google-plus-ios-sdk-1.7.1 sdk 登录 google-plus?

ios - 今天扩展支持 WatchConnectivity?