我在prepareForSegue回调中有NSOperationQueue和3个NSInvocationOperation,我需要在完成所有异步任务后移动到另一个视图控制器。 如何通知完成所有异步任务并且只有在移动到另一个屏幕后才会收到通知?
我尝试了这个没有成功:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
修改
似乎我不明白:
-(void)initPurchase{
[operationQueue cancelAllOperations];
NSInvocationOperation *downloadImageOperation = [[NSInvocationOperation alloc] initWithTarget:[BSImageDownloader getInstance] selector:@selector(downloadImageSync:) object:@"http://.........jpg"];
NSInvocationOperation *createImageOperation = [[NSInvocationOperation alloc] initWithTarget:[BSImageCreator getInstance] selector:@selector(createImage:) object:@"dsadsadsa"];
NSInvocationOperation *saveImageOperation = [[NSInvocationOperation alloc] initWithTarget:[BSImageSaver getInstance] selector:@selector(saveImageAsPng:) object:[BSSharedObject getInstance].createdImage];
[createImageOperation addDependency:downloadImageOperation];
[saveImageOperation addDependency:createImageOperation];
[operationQueue addOperation:downloadImageOperation];
[operationQueue addOperation:createImageOperation];
[operationQueue addOperation:saveImageOperation];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[[BSPopupManager getInstance]showWaitingPopup];
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
Purchase *purchase = [[Purchase alloc] init];
[purchase initPurchase];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[[BSPopupManager getInstance] closeWaitingPopup];
BSPurchaseViewController *purchaseViewController = [segue destinationViewController];
purchaseViewController.pngImage = [BSSharedObject getInstance].createdImage;
NSLog(@"2");
});
dispatch_release(group);
}
}
我仍然得到NSLog(@“2”);早于我在第三次NSInvocationOperation中保存图像
答案 0 :(得分:3)
如果您打算使用GCD执行异步任务,可以使用dispatch_group_async()
功能:Grand Central Dispatch (GCD) Reference
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
//Code here is executed asynchronously
});
dispatch_group_notify(group, dispatch_get_main_queue(),
^{
//Do something when async has completed
//Note: You are not required to use the main
//queue if you aren't performing any UI work.
});
dispatch_release(group);
答案 1 :(得分:1)
添加第四个操作,取决于在主线程上发布NSNotification的前三个操作。像
这样的东西NSOperation * completionOp = [NSBlockOperation blockOperationWithBlock:^{
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:MyOperationsCompletedNotification object:... userInfo:nil];
});
}];
[completionOp addDependency:op1];
[completionOp addDependency:op2];
[completionOp addDependency:op3];
[opQueue addOperation:op1];
[opQueue addOperation:op2];
[opQueue addOperation:op3];
[opQueue addOperation:completionOp];
我在代码中留下了...
,因为您可能希望使用除nil之外的其他内容填充对象字段(但它不应该是UIKit类,除了那些被记录为线程安全的类)。
或者,每个操作都可以通过dispatch_async()
或-performSelectorOnMainThread:
返回其结果,但同样,在块中引用线程不安全UIKit类的实例(或作为接收器)是不明智的或-performSelectorOnMainThread:
的对象。
有许多方法可以做到这一点,特别提到GameKit示例中的线程不安全 - 特别是,任何可能最终在UIView或UIViewController上调用-release
的东西都是危险的,因为这会导致{ {1}}在后台线程上调用。
答案 2 :(得分:0)
您可以使用键值观察来观察isFinished
的{{1}}属性。
答案 3 :(得分:0)
您可以使用swift 3中的dispatch_group使用GCD实现此目的。您可以在完成所有任务后收到通知。
let group = DispatchGroup()
group.enter()
run(after: 6) {
print(" 6 seconds")
group.leave()
}
group.enter()
run(after: 4) {
print(" 4 seconds")
group.leave()
}
group.enter()
run(after: 2) {
print(" 2 seconds")
group.leave()
}
group.enter()
run(after: 1) {
print(" 1 second")
group.leave()
}
group.notify(queue: DispatchQueue.global(qos: .background)) {
print("All async calls completed")
}