Victor Engel
Victor Engel

Reputation: 2113

What's a more efficient way to capture the screen in iPad?

I'm using the following method to capture an image of the top-level view of my app. It's surprisingly slow, though, so I'm looking for a faster alternative. Any suggestions? The log statements are just to capture timings.

+ (UIImage *) imageWithView:(UIView *)view{
   DLog(@"imageWityhView started");
   UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
   DLog(@"1");
   [view.layer renderInContext:UIGraphicsGetCurrentContext()];
   DLog(@"2");
   UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
   DLog(@"3");
   UIGraphicsEndImageContext();
   DLog(@"Returning an image");
   return img;
}

Results:

2013-11-17 11:30:47.196 ... imageWityhView started
2013-11-17 11:30:47.220 ... 1
2013-11-17 11:30:52.543 ... 2
2013-11-17 11:30:52.544 ... 3
2013-11-17 11:30:52.547 ... Returning an image

Unsurprisingly, the slow process is renderInContext:. Dispatching to a background thread because it's slow is not an option. The process is triggered by a user action, and the result is needed ASAP to give feedback to the user. Five seconds seems to be an absurd amount of time for something like this.

In my app, the view being captured could, potentially, have over 1300 subviews. However, for my testing, there were only about 20 or so. So what could be causing it to take so long? Is it triggering some method on all my subviews? Is there an efficient alternative to capture the full screen that I can use instead?

Upvotes: 0

Views: 137

Answers (1)

Victor Engel
Victor Engel

Reputation: 2113

Here is an updated method and resulting timings.

+ (UIImage *) imageWithView:(UIView *)view{
   UIImage *img;
   DLog(@"1");
   UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
   if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
      DLog(@"2");
      [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
      DLog(@"3");
      img = UIGraphicsGetImageFromCurrentImageContext();
   } else {
      [view.layer renderInContext:UIGraphicsGetCurrentContext()];
      img = UIGraphicsGetImageFromCurrentImageContext();
   }
   DLog(@"4");
   UIGraphicsEndImageContext();
   return img;
}

2013-11-17 12:54:03.568 ... 1
2013-11-17 12:54:03.592 ... 2
2013-11-17 12:54:03.740 ... 3
2013-11-17 12:54:03.741 ... 4

Total time reduced from 5.3 seconds to < 0.2 seconds. I may try to further reduce the time by using snapshotViewAfterScreenUpdates:, but for now, this suits my needs perfectly.

Upvotes: 1

Related Questions