2013-09-20 3 views
1

Программисты,Разрешено ли разрешение GCD dispatch_get_main_queue внутри блока?

Я делаю что-то принципиально неправильное со следующим кодом, поскольку он не работает при попытке получить основную очередь для запуска UIImageView? Это разрешено внутри блока? Мне нужно беспокоиться о том, чтобы получить основную очередь, или я должен просто запустить UIImageView непосредственно внутри блока? Если я установлю HUD.customView на нуль, это сработает. Я использую RestKit для отправки запроса POST и показывая MDProgressHUD, когда он выполняет вызов.

[objectManager.HTTPClient postPath:@"/items/create" 
         parameters:parameters 
          success:^(AFHTTPRequestOperation *operation, id responseObject){ 
           NSLog(@"Success!"); 

           __block UIImageView *imageView; 
           dispatch_sync(dispatch_get_main_queue(), ^{ 
            UIImage *image = [UIImage imageNamed:@"37x-Checkmark.png"]; 
            imageView = [[UIImageView alloc] initWithImage:image]; 
           }); 

           self.HUD.customView = imageView; 
           self.HUD.mode = MBProgressHUDModeCustomView; 
           self.HUD.labelText = @"Success"; 

           [self.HUD hide:YES afterDelay:1.5]; 
          } 
          failure:^(AFHTTPRequestOperation *operation, NSError *error){ 
           NSLog(@"Error: %@", [error localizedDescription]); 
           [self.HUD hide:YES afterDelay:2.0]; 
          }]; 

ответ

0

Там нет необходимости init UI-объектов в основном потоке. Но все операции с пользовательским интерфейсом должны выполняться в основном потоке. Итак, если вы хотите создать какое-то подвью или хотите получить некоторые данные, вы можете сделать это в фоновом режиме. Но если вы хотите добавить его на вид вашего контроллера или хотите перезагрузить просмотр, вы должны сделать это в основном потоке.

И да, dispatch_get_main_queue() разрешено внутри блоков.

1

UIKit не является потокобезопасным. Все, что связано с UIKit, должно выполняться в основном потоке. Выполнение операций с элементами UIKit на других потоках будет иметь непредсказуемые результаты, что здесь и есть.

Вам необходимо использовать код, связанный с HUD, в основном потоке. HUD также является элементом UIKit.

__weak YourClass *weakSelf = self; 
dispatch_sync(dispatch_get_main_queue(), ^{ 
    UIImage *image = [UIImage imageNamed:@"37x-Checkmark.png"]; 
    imageView = [[UIImageView alloc] initWithImage:image]; 

    //Modify the HUD 
    weakSelf.HUD.customView = imageView; 
    weakSelf.HUD.mode = MBProgressHUDModeCustomView; 
    weakSelf.HUD.labelText = @"Success"; 
    [weakSelf.HUD hide:YES afterDelay:1.5]; 
}); 

Одна предосторожности, при использовании self в блоках вам нужно создать и использовать weak ссылки, чтобы избежать сохранения цикла.

Надеюсь, что это поможет!

+0

Привет @Amar, могу ли я просто спросить, почему вы устанавливаете weakSelf = nil в своем блоке? Это освобождает память? Также, когда я пытаюсь сделать то же самое, я получаю ошибку компилятора: «Переменная не назначается (отсутствует спецификатор типа __block)». – amergin

+0

@amergin Это назначение не обязательно. – Amar

+0

Хорошо, спасибо @Amar - Я все еще пытаюсь размахивать блоками и ARC – amergin

0

Блоки success и failure уже вызваны в основной поток (вы можете добавить журнал, чтобы проверить, что это так), это делается для вас RestKit. Итак, когда вы вызываете dispatch_sync, вы можете блокировать основной поток, ожидающий себя. Поэтому, как правило, вы должны использовать dispatch_async, но в этом случае вам следует просто удалить этот попыток.

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