我的应用程序通过HTTP
请求发送大量消息。我在HTTP请求周围编写了一个简单的包装器,它有一个主要方法来触发请求并返回任何NSData
作为结果。
看起来像这样:
- (void)sendRequest:(NSURLRequest *)request {
[[[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
NSLog(@"---->> request returned");
if (_delegate == nil)
return;
if (error == nil) {
// forward along
[_delegate requestReturnedResult:data withResponse:response];
}
else {
// error occurred
[_delegate requestReturnedError:error withResponse:response];
}
}] resume];
}
这个HttpRequestHelper
对象是我的消息抽象对象ivar
的{{1}},它打包数据然后将其发送出去。
我认为有一个OutboundMessage
对象可以获取一些数据,创建一个MessageSender
对象并将其发送出去。
这种抽象很有效,除了我认为我遇到了ARC的问题。
当有人致电OutboundMessage
时,我[MessageSender send:]
alloc
并发送出去。
我通过OutboundMessage
看到的是我的NSLog
已清除(大概是OutboundMessage
退出时,我看到send
已清理。然后< / strong>我在HttpRequestHelper
的完成处理程序中看到NSLog
。
这向我表明,在HTTP请求完成之前,我的请求帮助程序周围的所有内容都已清除。然后你可以想象,我很快就会通过dataTaskWithRequest
冒出我的回复,我得delegate
。
我可以想出一些创造性的方法来防止重新分配并防止这种情况,但我想知道的是概念上处理这种触发消息模式的最佳做法是什么,只有在请求发生后才能清除包络对象完成。
感谢。
更新
每个包装器对象都使用exc_bad_access
样式模式,我注意到这些代理被保存为:
initWithDelegate:self
我将它们更改为@property (nonatomic, assign) id<HttpRequesterDelegate> delegate;
并且它似乎纠正了它,但我不确定我现在是否在泄漏记忆,或者是否有更优化的方法。
答案 0 :(得分:1)
首先,由NSURLSessionDataTask
方法创建的NSURLSession - dataTaskWithRequest:completionHandler:
对象保留completionHandler
块对象。在数据任务完成时执行块之前,块对象不会被释放。
接下来,Blocks自动捕获(保留)局部变量。代码中的以下行
if (_delegate == nil)
与
相同if (self.delegate == nil)
如果delegate
属性为strong
@property (nonatomic, strong) id<HttpRequesterDelegate> delegate;
然后self
被块保留。在这种情况下,self
是HttpRequestHelper
个对象。因此,只要数据任务完成,HttpRequestHelper
对象和delegate
对象就会生效。这很安全。
但delegate
属性为assign
@property (nonatomic, assign) id<HttpRequesterDelegate> delegate;
与__unsafe_unretained
相同。块根本不会保留__unsafe_unretained
个对象。因此self
未被保留,它将在数据任务完成之前被释放。
<强> ADDED 强>
在这种情况下,您可以使用局部变量来保留delegate
个对象。因为completionHandler仅使用delegate
对象,而不使用HttpRequestHelper
对象本身。
id<HttpRequesterDelegate> delegate = _delegate;
[[[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
NSLog(@"---->> request returned");
/*
* Use `delegate` instead of `_delegate`
*/
if (delegate == nil)
return;
...
在这种情况下,delegate
属性的属性很强或分配,它根本不重要。