我有一个UIlertView
询问用户他/她是否想要在执行数据之前备份数据。如果用户点击是,我做了类似这样的事情:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
if (buttonIndex != alertView.cancelButtonIndex)
[self backupData];
[self doSomethingWithData];
}
但是当用户解除UIAlertView
时,用户界面会冻结,直到backupData
和doSomethingWithData
方法完成。我认为在后台执行这些方法是不可接受的,因为doSomethingWithData
必须在backupData
完成时启动。
如何完全解除UIAlertView,然后启动backupData
或doSomethingWithData
方法?
答案 0 :(得分:2)
所以,解决方案很简单:
您不想冻结用户界面 ---> 使用后台执行调度程序;
您希望在备份后执行某些操作 ---> 传递阻止以完成。
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
__weak typeof (self) weakSelf = self;
[self backupDataWithCompletion:^(NSData *data) {
[weakSelf doSomethingWithData:data];
}];
});
}
}
- (void)backupDataWithCompletion:(void (^)(NSData *))completionBlock
{
NSData *data = //Do something
completionBlock(data);
}
或者另一个解决方案(不那么优雅)是将任务插入到主线程不起作用的SERIAL QUEUE中:
因此,在init
方法中初始化此队列:
_queue = dispatch_queue_create("backupQueue", DISPATCH_QUEUE_SERIAL);
queue是属性或var dispatch_queue_t queue;
然后:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex){
dispatch_async(queue, ^
{
[self backupData];
});
dispatch_async(queue, ^
{
[self doSomethingWithData];
});
}
}
答案 1 :(得分:0)
只需在后台执行这些方法即可。你最有可能在主线程上做一些沉重的事情,阻止UI。
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
//code in background
});
}
或者,您可以在后台运行一个方法,并在第一个方法完成后使用下面的代码在主线程上调用第二个方法。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
// do your background tasks here
[self doSomethingInBackground];
// when that method finishes you can run whatever you need to on the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
[self doSomethingInMainThread];
});
});
答案 2 :(得分:0)
你也可以这样做:
[self performSelector:@selector(doSomethingWithData) withObject:nil afterDelay:.1];
在您的变体中,它将在主线程中调用。
或
您还可以使用以下代码将其移至后台主题
[self performSelectorInBackground:@selector(doSomethingWithData) withObject:nil];
或
你可以在调度中使用大量的建议,结果将是相同的......