1

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>

ここで何が問題なのか理解できませんでしたか?デリゲートを呼び出すと正常に機能しますが、ブロックは常に呼び出されます。温かいご提案、ご感想を賜りますようお願い申し上げます。

4

1 に答える 1

4

NSOperationクラスリファレンス


completeBlock操作のメインタスクが完了したときに実行するブロックを返します

-(void(^)(void))completionBlock
戻り値
操作のメインタスクが完了した後に実行するブロック。このブロックはパラメーターを受け取らず、戻り値もありません。

説明指定した完了ブロックは、 isFinished メソッドによって返される値がYESに変更されたときに実行されます。したがって、このブロックは、操作のプライマリタスクが終了またはキャンセルされた後、操作オブジェクトによって実行されます。

操作をキューに配置すると、操作が完了またはキャンセルされたときに完了ブロックが呼び出されます。
また、「カスタム」完了ブロックがNSOperationの「completionBlock」に干渉している可能性があります。
I would suggest using a different name for your custom completionBlock,必要なのはNSOperationcompletionBlockの動作ではなく、他の何かだからです。

于 2012-11-14T03:14:11.243 に答える