基于earlier问题构建:
我的NSOperationQueue
看起来像这样:
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
[someObject someSelector];
}];
NSBlockOperation *block2= [NSBlockOperation blockOperationWithBlock:^{
[someObject anotherSelector];
}];
[block2 addDependency:block1];
[queue addOperation:block1];
[queue addOperation:block2];
现在,在someSelector
里面我有:
returnData = [requesterObj getDataWithURL:(NSString*)url];
其中getDataWithURL
包含以下内容:
NSURL *requestUrl = [NSURL URLWithString:strUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:timeout];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
现在,当我添加断点时,似乎在第一个块的NSURLConnection
完成之前调用了第二个块。大概是因为对getDataWithURL
的调用本身是异步的。在该请求返回之前,确保第一个块未完成的最佳方法是什么。我应该尝试使用NSInvocation
将数据放入returnData
吗?
答案 0 :(得分:1)
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
[someObject someSelector];
}];
这会创建一个“标准”块操作。即使从用户的角度来看异步网络操作没有完成,在执行块之后,此操作也被视为已完成([block1 isFinished]
为真)。
由于您不希望这样,因此您需要通过覆盖NSOperation
来明确来明确 通过覆盖其start
来告诉它:
- (void)completeOperation {
self.finished = YES;
self.executing = NO;
}
- (void)start {
if ([self isCancelled]) {
[self completeOperation];
return;
}
self.executing = YES;
[self main];
// this is where operation is set to finished in NSOperation
}
- (void)main {
[someObject someSelectorWithCompletionBlock: ^() {
[self completeOperation];
// retain cycle may exist unless completion block is destroyed afterwards
}];
}
答案 1 :(得分:1)
我个人更喜欢grand central dispatch,因为它使代码非常明显。此代码将按顺序调用两个选择器(来自另一个线程),然后在主线程上调用doneSelector
:
dispatch_async(dispatch_get_global_queue(0,0), ^{
// These will be called in sequence on a background thread
[someObject someSelector];
[someObject anotherSelector]
dispatch_async(dispatch_get_main_queue(), ^{
// These will be called on the main thread after the above are done
[someObject doneSelector];
NSLog(@"Finished operation");
});
});
答案 2 :(得分:0)
如果它适用于您的情况,我会让事情更简单并执行以下操作。
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
[someObject someSelector];
[someObject anotherSelector];
}];
[queue addOperation:block1];
答案 3 :(得分:0)
当您第一次发布your other question时,我猜测您可能一直在处理异步网络请求,如果您希望使用异步网络请求进行操作,通常会解决在子类{{1}中包含此类网络请求的问题。 } as I discussed in the answer to your other question(以及ilya随后也在这里描述)。
此处的问题表明您正在致电NSOperation
。如果这就是您所做的一切,那么就不需要sendSynchronousRequest
子类化模式,并且您应该能够毫无意外地使用NSOperation
。但是,看起来您发现addDependency
本身就是将getDataWithURL
提交给自己的操作队列,从而有效地使其异步。您正确地确定了如果从sendSynchronousRequest
中删除了冗余操作队列逻辑,那么您的问题就解决了,并且不需要getDataWithURL
子类化。
但是,我不会过于迅速地忽略这个子类NSOperation
模式,因为NSOperation
有一些限制你可能会妨碍自己。即,这些请求无法取消。同样,您无法在这些请求正在进行时获得进展,也无法处理任何高级功能,如质询 - 响应身份验证等。您可能不需要任何这些功能,但由于这些限制,我们中的许多人通常都会回避sendSynchronousRequest
(以及sendSynchronousRequest
)。
从长远来看,您可能会发现自己被基于NSURLConnectionDataDelegate
的网络呼叫所吸引,这些呼叫解决了这些限制。在这种情况下,此sendAsynchronousRequest
子类模式可能再次变得有用。或者,更好的是,考虑使用像AFNetworking这样的框架来提供基于NSOperation
的网络解决方案,但是为您做了很多这样的工作。