gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 10:10:08 24 4
gpt4 key购买 nike

我有一个 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 的引用,编译器会将其设为 global block ,并且它永远不会被释放。参见 http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com