我有一个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:方法中取消注释了对block的调用,但是正在调用该块,并且正在触发方法populateReceivedJSON。
对我来说更有趣的是log显示了与NSOperation子类相同的实例;
的 JSON --> <SKSimpleDownloadOperation: 0x7462be0>
我无法理解这里的问题是什么?当我调用delegate时它工作正常,但块总是被调用。我想提前感谢您的热情建议和想法。
答案 0 :(得分:4)
<强> completionBlock 强>
返回操作主要任务完成时要执行的块。- (void(^)(void))completionBlock
返回值
操作主要任务完成后执行的块。这个块没有 参数并没有返回值。讨论当isFinished方法返回的值更改为YES时,将执行您提供的完成块。因此,这个 在操作之后,操作对象执行块 主要任务已完成或取消。
如果您将操作放在队列上,则操作完成或取消时将调用完成块
此外,您的“自定义”完成块可能会干扰NSOperation的“completionBlock”
I would suggest using a different name for your custom completionBlock,
因为它不是您想要的NSOperation completionBlock的行为,而是其他内容。