保留他们刚刚传授的课程的块?

时间:2011-04-06 03:50:56

标签: ios cocoa-touch memory-management asihttprequest objective-c-blocks

我们有一个包装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),并且在发送后几乎立即开始解除分配(导致委托方法调用dealloced对象) )。使用同步NSURLConnection,从未发生过。

我认为它会被异步释放,但我如何恰当地保留request?如果我在创建它之后立即保留它,我必须在回调中释放它,但是如果请求被取消则不会调用回调,并且会产生内存泄漏。

2 个答案:

答案 0 :(得分:2)

  

该块对保留请求计数的作用是什么?是复制还是保留它?

不,它没有。

Request * request = [Request requestWithURL:url];
[request sendWithCallback:^(Request * request) {
    // The request argument shadows the request local variable,
    // this block doesn't retain the request instance.
}]

如果块没有请求参数,

Request * request = [Request requestWithURL:url];
[request sendWithCallback:^{
    // If you use the request local variable in this block,
    // this block automatically retains the request instance.
}]

在这种情况下,它会导致保留周期(请求保留块,块保留请求)。

请查看我的AsyncURLConnection类。 NSURLConnection保留AsyncURLConnection实例,因此您不需要自己拥有AsyncURLConnection。

如何使用

[AsyncURLConnection request:url completeBlock:^(NSData *data) {
    // Do success stuff
} errorBlock:^(NSError *error) {
    // Do error stuff
}];

答案 1 :(得分:0)

块不会自动保留或复制对象参数。它与将对象参数传递给方法或函数的语义相同 - 如果在块,方法或函数使用参数完成之前,当前自动释放池有可能耗尽,则块,方法或函数应保留其参数。

请注意您方案中的工作流程。这段代码:

Request * request = [Request requestWithURL:url];
[request sendWithCallback:^(Request * request) {
    // do some stuff
}];

尚未执行该块,也不会将任何参数传递给该块。它创建一个块并将其作为参数传递给-sendWithCallback:。该块有一个名为request的{​​{1}}类型的参数,但实际参数尚未通过。

稍后在您的代码中,并假设您已将块存储在Request *中,该块将被调用为:

callback

callback(someRequest); // or callback(self);

self.callback(someRequest); // or self.callback(self);

取决于谁负责调用它。此时,无论谁调用回调都应该引用有效请求(aRequest.callback(someRequest); // or someRequest.callback(someRequest); ),该请求是传递给块的参数。