注意:这个类似的 SO question讨论了如何构建相同的类,但没有解决我与使用该类相关的内存管理问题。
我想使用sendAsynchronousRequest:queue:completionHandler:
,但我需要支持 iOS 4.2。因此,我创建了一个名为的自定义类JCURLRequest
,它使用NSURLConnection
并生成了一个不错的接口:
- (void)sendRequest:(NSURLRequest *)request
responseHandler:(JCURLResponseHandler)responseHandler;
我有一个关于使用这个类的问题(我在 ARC 内存管理中):
- 当我创建我的 JCURLRequest 对象时,我需要保留对该对象的引用吗?还是我可以“开火然后忘记它”?
注意:我了解 ARC 的基础知识 - 如果您有一个指向对象的指针,它将保持活动状态,如果没有更多指向对象的指针,它将在下一个自动释放池中释放。
因此,我想知道 - 我可以像(1)那样称呼它还是我需要使用(2)
(1)
JCURLRequest *jcURLRequest = [[JCURLRequest alloc] init];
[jcURLRequest sendRequest:myRequest
responseHandler:^(NSData *data, NSError *error) { ... }];
// Assuming I don't maintain a reference to jcURLRequest after this
(2)
// Assume @property (strong) JCURLRequest *jcURLRequest;
// @synthesize jcURLRequest = _jcURLRequest;
self.jcURLRequest = [[JCURLRequest alloc] init];
[self.jcURLRequest sendRequest:myRequest
responseHandler:^(NSData *data, NSError *error) { ... }];
NSURLConnection
使用异步回调,所以我的想法是我必须使用(2)。这是因为 - 当委托回调“回调”时,jcURLRequest 实例可能已经在自动释放池中被清理了。
不过我很困惑,因为我已经用 (1) 进行了测试,它“似乎”工作正常。但是,我的想法是,它的工作可能只是巧合 - 即。确实没有更多指向 jcURLRequest 对象的有效指针,但 iOS 只是还没有解决它。
以下是完整的JCURLRequest
课程供参考
// JCURLRequest.h
#import <Foundation/Foundation.h>
typedef void (^JCURLResponseHandler) (NSData *data, NSError *error);
@interface JCURLRequest : NSObject
- (void)sendRequest:(NSURLRequest *)request responseHandler:(JCURLResponseHandler)responseHandler;
@end
// JCURLRequest.m
#import "JCURLRequest.h"
@interface JCURLRequest ()
{
JCURLResponseHandler responseHandler;
}
@property (strong, nonatomic) NSMutableData *responseData;
@end
@implementation JCURLRequest
@synthesize responseData = _responseData;
#pragma mark - Public API
- (void)sendRequest:(NSURLRequest *)request responseHandler:(JCURLResponseHandler)handler
{
responseHandler = [handler copy];
dispatch_async(dispatch_get_main_queue(), ^{
__unused NSURLConnection *connectionNotNeeded = [[NSURLConnection alloc] initWithRequest:request delegate:self];
});
}
#pragma mark - Private API
- (NSMutableData *)responseData
{
if (!_responseData)
{
_responseData = _responseData = [[NSMutableData alloc] initWithLength:0];
}
return _responseData;
}
#pragma mark - URL Connection Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
responseHandler(nil, error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
responseHandler([NSData dataWithData:self.responseData], nil);
}
@end