我已经在同一个项目上工作了一段时间,而且我对Objective-C和Cocoa的理解已经发展了一段时间。回顾一下代码的某些部分,我看到了:
__weak ASIFormDataRequest *serverQueueRequest = [ASIFormDataRequest requestWithURL:url2];
[serverQueueRequest setCompletionBlock:^{
NSLog(@"%@", serverQueueRequest.responseString);
}];
[serverQueueRequest startAsynchronous];
这就是我处理所有服务器请求的方式。我想我这样做是为了抑制警告,即“在块中捕获请求可能会导致保留周期”。所以我把它变弱了,这似乎解决了我所有的问题。我没有发现任何真正的问题。
但是,现在查看代码,它的工作原理似乎有些奇怪。当我将请求声明为__weak
时,它不应该立即归零,因为没有人坚持它吗?为什么这段代码有效?
此外,虽然这段代码有效,但我最近发现了一个不这样的情况:当连续多次调用包含此代码的方法时,在一秒钟内调用5次,3/5请求将得到NULL
回复。情况一直如此。删除__weak
限定符可解决此问题。对此有何解释?
最后,声明像这样的本地请求的正确方法是什么?
更新:根据this question,正确的方法就是这样:
ASIHTTPRequest *_request = [[ASIHTTPRequest alloc] initWithURL:...
__weak ASIHTTPRequest *request = _request;
编辑:实际上上面的修复不能解决调用代码5次导致NULL响应的问题。那个问题依然存在。问题消失的唯一方法是强烈捕获请求而不使用任何限定符。
现在的问题是为什么我的原始代码仍然有效..
答案 0 :(得分:3)
引自Apple's Programming with ARC发行说明:
在堆栈上使用__weak变量时要小心。考虑一下 以下示例:
NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
NSLog(@"string:%@", string);
虽然在初始分配后使用了字符串, 当时没有对字符串对象的其他强引用 分配;因此,它立即被解除分配。日志声明 表明字符串具有空值。
答案 1 :(得分:0)
我相信这是因为你在一个块中运行弱变量。该块保持弱变量的状态,从而使其起作用。一旦块完成,我就会对变量进行大量工作可能会导致问题。
我猜测如果你多次运行它失败的原因是因为异步asi调用堆栈变得很高并且炸弹。我以前见过这个,如果你很耐心,你可以在调试器中看到asi爆炸。
答案 2 :(得分:0)
obj C堆栈将始终保留范围内的指针。 _weak并不意味着现在释放它意味着当堆栈超出范围时释放。
当你声明一个var然后在同一个堆栈范围内对它进行调用时,它将不会被释放,直到(最低限度)清理堆栈。
阻止扩展方法范围,因为它们意味着潜在的异步行为,并且它们利用调用它们时存在的堆栈。