NSOperationカスタムクラスがあり、完了ブロックを割り当てることができるように、簡単にブロックを受け入れるメソッドを追加しました。しかし、私がブロックを呼び出さなくても、それはメインの呼び出しクラスに返され、それ自体が渡された状態でメッセージを送信します。
Interface :
@class SKSimpleDownloadOperation;
typedef void(^CompletionBlock)(id Json, NSError *error);
@protocol SKSimpleDownloadDelegate <NSObject>
-(void)operation:(SKSimpleDownloadOperation*)operation didCompleteWithData:(NSData*)data;
-(void)operation:(SKSimpleDownloadOperation*)operation didFailWithError:(NSError*)error;
@end
@interface SKSimpleDownloadOperation : NSOperation
@property(nonatomic, assign) NSInteger statusCode;
-(id)initWithUrlRequest:(NSURLRequest*)request andDelegate:(id<SKSimpleDownloadDelegate>)aDelegate;
-(id)initWithUrlRequest:(NSURLRequest*)request andDelegate:(id<SKSimpleDownloadDelegate>)aDelegate withCompletionBlock:(void(^)(id json, NSError *error))completionBlock;
@end
Implementation:
@interface SKSimpleDownloadOperation()<NSURLConnectionDataDelegate>
@property(nonatomic, strong) NSURLRequest *request;
@property(nonatomic, strong) NSMutableData *data;
@property(nonatomic, assign) id<SKSimpleDownloadDelegate>delegate;
@property(nonatomic, copy) CompletionBlock completionBlock;
@end
@implementation SKSimpleDownloadOperation
@synthesize delegate;
@synthesize request;
@synthesize statusCode;
@synthesize completionBlock;
-(id)initWithUrlRequest:(NSURLRequest *)aRequest andDelegate:(id<SKSimpleDownloadDelegate>)aDelegate withCompletionBlock:(void (^)(id, NSError *))aCompletionBlock{
if(!(self = [super init])) return nil;
[self setRequest:aRequest];
[self setDelegate:aDelegate];
[self setCompletionBlock:aCompletionBlock];
return self;
}
-(id)initWithUrlRequest:(NSURLRequest *)aRequest andDelegate:(id<SKSimpleDownloadDelegate>)aDelegate{
return [self initWithUrlRequest:aRequest andDelegate:aDelegate withCompletionBlock:nil];
}
-(void)main{
[NSURLConnection connectionWithRequest:[self request] delegate:self];
CFRunLoopRun();
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response{
[self setStatusCode:[response statusCode]];
[self setData:[NSMutableData data]];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)newData{
[[self data] appendData:newData];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
if(self.delegate && [self.delegate respondsToSelector:@selector(operation:didCompleteWithData:)])
[[self delegate] operation:self didCompleteWithData:[self data]];
CFRunLoopStop(CFRunLoopGetCurrent());
// if(completionBlock != nil){
// [self performSelector:@selector(callBlockWithNecessaryParameter) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];
// }
}
-(void)callBlockWithNecessaryParameter{
NSError *error = nil;
id object = [NSJSONSerialization JSONObjectWithData:[self data] options:NSJSONReadingAllowFragments error:&error];
// completionBlock(object,error);
//completionBlock = nil;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
[[self delegate] operation:self didFailWithError:error];
CFRunLoopStop(CFRunLoopGetCurrent());
}
@end
オペレーションの呼び方;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://query.yahooapis.com/v1/public/yql?q=select%20item%20from%20weather.forecast%20where%20location%3D%2248907%22&format=json"]];
ViewController __weak *__viewController = self;
NSOperation *operation = [[SKSimpleDownloadOperation alloc] initWithUrlRequest:request andDelegate:nil withCompletionBlock:^(id json, NSError *error) {
[__viewController populateReceivedJSON:json];
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
operation = nil;
queue = nil;
-(void)populateReceivedJSON:(id)json{
NSLog(@"JSON --> %@", json);
}
上記のコードでわかるように、connectionDidFinishLoading:メソッドでブロックの呼び出しのコメントを解除しましたが、ブロックが呼び出され、メソッドpopulateReceivedJSONがトリガーされています。
そして私にとってもっと興味深いのは、ログがNSOperationサブクラスの同じインスタンスを示していることです。
JSON --> <SKSimpleDownloadOperation: 0x7462be0>
ここで何が問題なのか理解できませんでしたか?デリゲートを呼び出すと正常に機能しますが、ブロックは常に呼び出されます。温かいご提案、ご感想を賜りますようお願い申し上げます。