注意:This similar SO question討論如何構建相同的類,但未解決與使用該類有關的內存管理問題。我想用sendAsynchronousRequest:queue:completionHandler:
,但是我需要支持iOS 4.2。因此,我創建了一個名爲JCURLRequest
的自定義類使用NSURLConnection
並生成漂亮的界面:我是否需要保留我的自定義NSURLConnection包裝對象的所有權? (在ARC環境中)
- (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
不知道關於NSURLConnection - 謝謝,這非常有幫助。我發現在[特殊考慮](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/doc/uid/ 20001697-BAJDDIDG)你會看到這個官方文檔。關於'__unused',我用它來抑制'Expression result unused'的警告。你知道另一種方法來抑制這種警告嗎? – bearMountain 2012-04-24 16:54:19
同時在塊內引用'self'會導致它被保留。 – Joe 2012-04-24 17:19:47
@bearMountain另一種抑制警告的方法是不存儲表達式結果! (如上所示)。如果您不打算使用該變量,則不需要存儲它。 – joerick 2012-04-25 08:36:11