注:この同様の SO の質問では、同じクラスを構築する方法について説明していますが、クラスの使用に関連するメモリ管理の問題には対処していません。
を使用したいのですがsendAsynchronousRequest:queue:completionHandler:
、iOS 4.2 をサポートする必要があります。したがって、 Nice インターフェース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