5

I have an app in which the screen continuously is capturing in background thread. Here is the code

- (UIImage *) captureScreen {

    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    CGRect rect = [keyWindow bounds];
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [[keyWindow layer] renderInContext:context];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if ((orientation == UIInterfaceOrientationLandscapeLeft) || (orientation == UIInterfaceOrientationLandscapeRight) || (orientation==UIInterfaceOrientationPortraitUpsideDown)) {
        img=[self rotatedImage:img];
    }
    return img;
}

It works good for capturing once or twice. But after a while the app crashes always on the same line [[keyWindow layer] renderInContext:context]; and it gives EXC_BAD_ACCESS (code=1, address=0x8) message. I searched everywhere and nothing useful. Found only that renderInContext has memory leak issue when it works in background thread. But as you understand that doesn't solve my issue :) . So have 3 questions :-

  1. What is the reason of this crash (problem)?

  2. What can I do with this?

  3. Is there any other way to capture screen (beside the one that Apple suggests, because there renderInContext is also used). Something without rendering...?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Garnik
  • 423
  • 1
  • 6
  • 20
  • you should perform your GUI related tasks on main thread – nsgulliver Feb 28 '13 at 12:13
  • show us your rendering code. are you attempting to use core data objects in a thread that they were not created on. are you using non-atomic properties in your rendering code. both of these and more could cause this. – Warren Burton Feb 28 '13 at 12:38
  • Is any of `layer` or `context` nil when calling `renderInContext`? Is the `receivedMemoryWarning` method being called? – ott-- Feb 28 '13 at 13:15
  • @WarrenBurton I'm writing kind of a library so my code cannot be based on main thread only. I have two other threads one for capturing another for sending the image. So yes maybe I'm using core data objects created in main thread. Also can you explain why non-atomic property is so important here??? – Garnik Feb 28 '13 at 13:29
  • @ott-- I'm not sure about layer and context cz haven't checked...But in some cases when crash happens I get "Recieved Memory Warning" message and in some cases I don't. Trying still... :( – Garnik Feb 28 '13 at 13:32
  • actually Fabiens answer is correct , if your rendering code was duff for threading it would show up in the stack trace. You most likely have to create a fresh context for the thread rather than trying to re-use the one from another thread. – Warren Burton Feb 28 '13 at 13:43
  • but in code above I use context that is created in the same method, which means it is in the same thread...what is the problem here? – Garnik Feb 28 '13 at 14:04
  • also I would like to mention that crash almost always happens on websites which has semi-transparent overlay. (My App has webview in which I can load different websites to test app). – Garnik Feb 28 '13 at 15:22
  • HI,Have you found a solution for this,im also having same problem?If so pls share the solution – Infaz Dec 20 '15 at 17:39

2 Answers2

8

-renderInContext: is not thread-safe and you can't call it from a background thread. You'll have to do the drawing on the main thread.

Fabian Kreiser
  • 8,307
  • 1
  • 34
  • 60
  • But if I do cyclic capturing in main thread, the UI will stuck, right? This way it works, but crashes, and may be the reason is that it is not thread safe... :( ??? – Garnik Feb 28 '13 at 13:23
  • This is right, you're UI will lock while you are rendering the screenshots. Means you'll have to find a user friendly way to make this happen, throwing up a HUD or something similar. – Alfie Hanssen Apr 04 '13 at 15:25
  • I have the same issue, on background thread renderincontext crashes some times. Can you expand on the HUD comment? – Gamma-Point Apr 06 '13 at 04:57
  • @Gamma-Point By HUD he meant that you can use a sort of a loader and prevent users interaction with the view. Here is the link to a good implementation of the HUD Component https://github.com/jdg/MBProgressHUD – aumanets Apr 23 '14 at 12:38
3

I had nothing to do but performing this method on main thread. I reorganized my thread management and could get good result for me doing this:

[self performSelectorOnMainThread:@selector(captureScreenOnMainThread) withObject:nil waitUntilDone: YES]; Last parameter can be set to no in some cases...

Thanks for all responses.

Garnik
  • 423
  • 1
  • 6
  • 20