2014-10-17 3 views
0

У меня есть UIlertView, чтобы спросить пользователя, хочет ли он делать резервные копии данных перед выполнением чего-либо с данными. Я сделал что-то вроде этого, чтобы захватить, если пользователь постучала Да:Выполнение задачи после отклонения UIAlertView

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
    if (buttonIndex != alertView.cancelButtonIndex) 
     [self backupData]; 

    [self doSomethingWithData]; 
} 

Но когда пользователь закрывает UIAlertView интерфейс будет замерзла, пока backupData и doSomethingWithData методов полной. Я думаю, что выполнение этих методов в фоновом режиме неприемлемо, так как doSomethingWithData должен быть запущен, когда закончится backupData. Как я могу полностью удалить UIAlertView, а затем запустить backupData или doSomethingWithData методов?

+0

Выполняйте длинные действия в фоновом режиме. – rmaddy

ответ

2

Итак, решение является простым у:

Вы не хотите заморозить UI --->Использование фона исполнение с диспетчером;

Вы хотите выполнить что-то после резервного копирования --->Pass блок для завершения.

-(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 ОЧЕРЕДЬ, которые не работают в основном потоке:

Так инициализации этой очереди в вашем init метод:

_queue = dispatch_queue_create("backupQueue", DISPATCH_QUEUE_SERIAL); 

очередь является свойством или вар 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]; 
     }); 

    } 
} 
+0

Почему вы использовали 'weakSelf' для второго метода, а не просто' self'? – Hadu

+0

Чтобы избежать цикла сохранения –

+0

Первый метод не работал для меня. Метод doSomethingWithData не вызван. – Hadu

0

Просто выполните эти методы в фоновом режиме. Вы, скорее всего, делаете некоторые тяжелые вещи в основном потоке, блокируя пользовательский интерфейс.

-(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]; 
    }); 
}); 
+0

Когда вы запускаете [self doSomethingInBackground] в фоновом режиме, почему приложение будет ждать, пока оно закончится, а затем перейдет к [self doSomethingInMainThread]? – Hadu

0

Вы также можете сделать это нравится:

[self performSelector:@selector(doSomethingWithData) withObject:nil afterDelay:.1]; 

в вашем варианте он будет называться в основном потоке.

ИЛИ

вы также можете использовать этот код, чтобы переместить его в фоновый поток

[self performSelectorInBackground:@selector(doSomethingWithData) withObject:nil]; 

ИЛИ

вы можете использовать множество предложений с депеш, результат будет таким же ...

Смежные вопросы