DrawViewHierarchyInRect in background thread

I am trying to do some “off-screen rendering” in the background thread to update the preview of the design application that I am creating.

I used renderInContext in the renderInContext queue to accomplish this, but notice that it is slow.

So, I started using drawViewHierarchyInRect , which works great and much faster. However, I noticed that my interface is completely blocked when this method is run in b / g.

If I do this in the main thread ...

  UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)]; preview.backgroundColor = [UIColor redColor]; UIGraphicsBeginImageContextWithOptions(preview.bounds.size, NO, 0.0); BOOL ok = [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; UIImage *img = nil; if( ok ) { img = UIGraphicsGetImageFromCurrentImageContext(); } UIGraphicsEndImageContext(); 

... everything is working fine.

However, if I (say) post this ...

 if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) { dispatch_async(renderQueue, ^{ // capture UIView *preview = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)]; preview.backgroundColor = [UIColor redColor]; UIGraphicsBeginImageContextWithOptions(preview.bounds.size, NO, 0.0); BOOL ok = [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; UIImage *img = nil; if( ok ) { img = UIGraphicsGetImageFromCurrentImageContext(); } UIGraphicsEndImageContext(); } dispatch_semaphore_signal(semaphore); }); 

... my user interface freezes completely after execution.

'ok' returns YES, so everything works.

If I set afterUpdates to NO, "ok" will be NO (unsuccessfully), but the user interface continues to respond.

Are there any restrictions on using drawViewHierarchyInRect with anything other than the main thread?

+8
multithreading ios uiview screenshot
source share
2 answers

UIKit objects should only be processed in the main thread. Apple Documentation UIKit mentions this saying

For the most part, use UIKit classes only from the main application stream. This is especially true for classes derived from UIResponder, or which include controlling your application user interface in any way.

+1
source share

Are you calling the above dispatch_async from the main thread? my theory here is that you called [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; with YES , which needs to execute some code in the main thread, however the main thread is blocked on the semaphore. What you probably want to do is exit to the main thread from time to time, so drawViewHierarchyInRect may end.

 __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); dispatch_async(renderQueue, ^{ /// your code here /// ... BOOL ok = [preview drawViewHierarchyInRect:preview.bounds afterScreenUpdates:YES]; ..... dispatch_semaphore_signal(sema); }); while (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; } 
0
source share

All Articles