2013-06-28 4 views
4

Я пытаюсь загрузить файл с сторонней библиотекой AFNetworking, В его основе находится объект NSOperation, для которого можно установить блок завершения, когда загрузка закончил.animateWithDuration не запускается должным образом, когда в NSOperation completeBlock

Каким-то образом animateWithDuration: в этом блоке не работает должным образом: оба блока завершения и фактическая анимация задерживаются на ~ 5 или 60 секунд или вообще не запускаются. Единственный способ узнать, что он начинается вообще, - это вызов NSLog.

Позвольте мне продемонстрировать это:

выход
[UIView animateWithDuration:0.1 
    animations:^{ 
     controller.view.alpha=0.5; 
     NSLog(@"First Try Start"); 
    } 
    completion:^(BOOL finished) { 
     NSLog(@"First Try End"); 
}]; 


// Here comes the NSOperation completion block 
[self->currentConnection setCompletionBlock:^{ 
     NSLog(@"downloadComplete!"); 
     [UIView animateWithDuration:0.1 
      animations:^{ 
       controller.view.alpha=0.5; // this doesn't run immediately, only the NSLog line 
       NSLog(@"Second Try Start"); 
    } 
    completion:^(BOOL finished) { 
          NSLog(@"Second Try End"); 
    }]; 
}]; 

консоли:

2013-06-28 23:22:11.374 Molto Luce[7831:c07] First Try Start 
2013-06-28 23:22:11.477 Molto Luce[7831:c07] First Try End 
2013-06-28 23:22:11.742 Molto Luce[7831:1303] downloadComplete! 
2013-06-28 23:22:11.745 Molto Luce[7831:1303] Second Try Start 
2013-06-28 23:23:05.007 Molto Luce[7831:c07] Second Try End 

Помощь ценится!

ответ

5

UIKit не является особенно надежным в потоковом режиме. Манипулирование объектами UIKit в потоках, отличных от основного потока, приведет к непредсказуемым результатам, главным образом в виде объектов, которые явно не реагируют на изменения состояния.

Вы можете использовать НОД в вашем блоке завершения запланировать блок для запуска на главной теме:

[self->currentConnection setCompletionBlock:^{ 
    NSLog(@"downloadComplete!"); 
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 
    dispatch_async(mainQueue, ^{ 
     [UIView animateWithDuration:0.1 
      animations:^{ 
        controller.view.alpha=0.5; 
        NSLog(@"Second Try Start"); 
      } 
      completion:^(BOOL finished 
       NSLog(@"Second Try End"); 
      } 
     ]; 
    }); 
}]; 
+0

Хотя я до сих пор не понимаю, почему это не сработало в первую очередь, я знаю, откуда вы и что самое главное, ваше исправление работает! Благодарю. – Eric

+0

Этот ответ спас меня много времени. Следует отметить, что с Xcode 5 мне нужно было удалить «пустоту». dispatch_get_main_queue(); работал на меня. –

+0

Это, должно быть, артефакт для копирования и вставки. Я отредактировал его. –

0

// определяем следующий метод в своем классе

-(void)updateView:(UIView *)paramView { 
    paramView = 0.5 
} 

// И вызов следующий строка кода, где вы устанавливаете controller.alpha = 0.5 // Как сейчас вы обновляете альфа на основной нити

[self performSelectorOnMainThread:@selector(updateView:) withObject:controller.view waitUntilDone:YES]; 
+0

Мне явно нужно запустить эту строку в функции обратного вызова. Насколько мне известно, нет другого способа получить уведомление о том, когда сетевой запрос будет выполнен. – Eric