块保留它们刚刚传递到的类吗?
我们有一个包装 NSURLConnection 的类。它接受一个块,并在完成加载时回调该块。为了给您一个想法,请参阅下文。当您发送请求时,它会将回调保存在实例上。假设我的类名为 Request
// from Request.h
@property (nonatomic, copy) void(^callback)(Request*);
- (void) sendWithCallback:(void(^)(Request*))callback;
我使用的代码如下所示:
Request * request = [Request requestWithURL:url];
[request sendWithCallback:^(Request * request) {
// do some stuff
}]
我的问题是:该块对 request
的保留计数有何作用?它复制/保留它吗?请注意,我没有将 __block 放在定义前面。
我刚刚更改了 Request
中的一些主要内容(从同步 NSURLConnection
切换到异步 ASIHTTPRequest
),并且它在发送后几乎立即开始释放(导致委托)调用已释放对象的方法)。使用同步 NSURLConnection
后,这种情况从未发生过。
我想它会通过异步释放是有道理的,但是我如何适当地保留 request
呢?如果我在创建它后立即保留它,我必须在回调中释放它,但如果请求被取消,回调不会被调用,并且会造成内存泄漏。
We have a class that wraps NSURLConnection. It accepts a block that it calls back when it finishes loading. To give you an idea, see below. When you send a request, it saves the callback on the instance. Assume my class is named Request
// from Request.h
@property (nonatomic, copy) void(^callback)(Request*);
- (void) sendWithCallback:(void(^)(Request*))callback;
My code to use one looks something like this:
Request * request = [Request requestWithURL:url];
[request sendWithCallback:^(Request * request) {
// do some stuff
}]
My question is: what does the block do to the retain count of request
? Does it copy/retain it? Notice that I didn't put __block
in front of the definition.
I just changed something major in Request
(switched from a synchronous NSURLConnection
to async ASIHTTPRequest
), and it started deallocing almost immediately after sending (causing delegate methods to call a dealloced object). With the sync NSURLConnection
, that never happened.
I guess it makes sense that it would get dealloced with async, but how would I retain request
appropriately? If I retained it right after I created it, I'd have to release it in the callback, but the callback doesn't get called if the request is cancelled, and would create a memory leak.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,事实并非如此。
如果块没有请求参数,
在这种情况下,会导致保留循环(请求保留块,块保留请求)。
请看一下我的 AsyncURLConnection 类。 NSURLConnection 保留 AsyncURLConnection 实例,因此您自己不拥有 AsyncURLConnection 内容。
如何使用
No, it doesn't.
If the block doesn't have the request argument,
In this case, it would cause retain cycles (the request retains the block, the block retains the request).
Please take a look at my AsyncURLConnection class. NSURLConnection retains AsyncURLConnection instance, so you don't own AsyncURLConnection stuff by yourself.
How to use
块不会自动保留或复制对象参数。它与将对象参数传递给方法或函数的语义相同 - 如果当前自动释放池有可能在块、方法或函数完成使用参数之前耗尽,则块、方法或函数应该保留其参数。
请注意您的场景中的工作流程。此代码:
尚未执行该块,也没有向该块传递任何参数。它创建一个块并将其作为参数传递给
-sendWithCallback:
。该块有一个名为request
的参数,类型为Request *
,但实际参数尚未传递。在代码稍后的某个时刻,假设您已将该块存储在
callback
中,则该块将被称为:or
or ,
具体取决于谁负责调用它。此时,调用回调的人都应该拥有对有效请求 (
someRequest
) 的引用,并且该请求是传递给块的参数。Blocks won’t automatically retain or copy object arguments. It’s the same semantics as passing object arguments to methods or functions — the block, method, or function should retain its arguments if there’s potential for the current autorelease pool to drain before the block, method, or function has finished using the arguments.
Note the workflow in your scenario. This code:
does not execute the block yet, nor does it pass any argument to the block. It creates a block and passes it as an argument to
-sendWithCallback:
. The block has a parameter calledrequest
of typeRequest *
but the actual argument hasn’t been passed yet.At some point later in your code, and assuming you’ve stored the block in
callback
, that block will be called as:or
or
depending on who’s responsible for calling it. At this point, whoever calls the callback should have a reference to a valid request (
someRequest
), and that request is the argument passed to the block.