AnimateWithDuration not executing properly when NSOperationBlock is executing

I'm trying to download a file with a third-party AFNetworking library. At its core, there is an NSOperation object for which you can set a completion block when the download is complete.

Somehow, animateWithDuration: inside this block does not work correctly: both completion blocks and the actual animation are delayed by ~ 5 or 60 seconds or do not start at all. The only way to find out that it starts at all is to call NSLog.

Let me demonstrate this:

 [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"); }]; }]; 

Console output:

 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 

Help is appreciated!

+4
source share
2 answers

UIKit is not particularly thread safe. Manipulating UIKit objects in threads other than the main thread will produce unpredictable results, mainly in the form of objects that do not explicitly respond to state changes.

You can use the GCD in your completion block to schedule the block to run in the main thread:

 [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"); } ]; }); }]; 
+5
source

// define the next method in your class

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

// And call the next line of code where you set controller.alpha = 0.5 // How do you now update the alpha in the main thread

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

Source: https://habr.com/ru/post/1488772/


All Articles