Search code examples
ipadios6uiwebviewcore-graphicscalayer

iOS app crashing while rendering webview layer using renderInContext: api


I am loading a ppt file from email using UIWebView and converting the ppt pages to images using renderInContext: api in a do while loop on main thread.

It is working fine when I load small ppt files having less than 50 slides. My app is crashing when I load 100 page ppt documents. The crash is happening exactly 83rd time at renderInContext: API (render UILayer from UIWebview).

Below is the piece of code I am using in ARC application.

do
    {
        @autoreleasepool
        {
            NSLog(@"Image Index: %d",i);
            UIGraphicsBeginImageContext(CGSizeMake(768.0f, 576.0f));
            CGContextRef ctxCurrentGraphics = UIGraphicsGetCurrentContext();

            [webView.layer renderInContext:ctxCurrentGraphics];
            CGContextSetInterpolationQuality(ctxCurrentGraphics, kCGInterpolationHigh);
            CGContextSetRenderingIntent(ctxCurrentGraphics, kCGRenderingIntentDefault);
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

            UIGraphicsEndImageContext();

            /******* Each snap shot been inserted to db before new snapshot created ********/

            if (image != nil)
            {
                [[DataManager instance] insertImportedImageToDb:image importFileName:filename ...];
                slideID++;
                seqID++;
            }

            [webView.scrollView scrollRectToVisible:CGRectMake(0.0f, (i * 581.3) , webView.bounds.size.width, webView.bounds.size.height) animated:NO];
            scrolloffset = scrolloffset + 581.3;

            i++;

            /***** check if ppt contains only one page ****/
            if (webView.scrollView.contentSize.height == 1004.0 || webView.scrollView.contentSize.height == 1005.0)
            {
                break;
            }

            image = nil;
        }
    }
    while (scrolloffset <= webView.scrollView.contentSize.height);

The app is crashing only on device (iOS6). I tried all alternatives which I find in Stack Overflow like clearing context, usage of @autoreleasepool etc.

Is there any way I can optimize the memory usage or is there any alternative to renderInContext: API where it seems this api has memory leak?

Edit1: Most of the time application received 'Low Memory warnings' but twice I see the below crash log:

Last Exception Backtrace:
0   CoreFoundation                  0x316aa29e 0x315e8000 + 795294
1   libobjc.A.dylib                 0x3954e97a 0x39546000 + 35194
2   CoreFoundation                  0x316aa1c0 0x315e8000 + 795072
3   UIKit                           0x3389dd5a 0x334af000 + 4123994
4   MyApplication                   0x000c590c 0xa3000 + 141580
5   MyApplication                   0x000c4d26 0xa3000 + 138534
6   Foundation                      0x31fc1f4e 0x31f10000 + 728910
7   CoreFoundation                  0x3167f5da 0x315e8000 + 619994
8   CoreFoundation                  0x3167f28c 0x315e8000 + 619148
9   CoreFoundation                  0x3167defc 0x315e8000 + 614140
10  CoreFoundation                  0x315f0eb8 0x315e8000 + 36536
11  CoreFoundation                  0x315f0d44 0x315e8000 + 36164
12  GraphicsServices                0x351a52e6 0x351a0000 + 21222
13  UIKit                           0x335062fc 0x334af000 + 357116
14  MyApplication               0x000a8c60 0xa3000 + 23648
15  libdyld.dylib                   0x39985b1c 0x39984000 + 6940

Solution

  • The root cause of the issue is recursively capturing images from webview where renderInContext: is used to capture.

    The problem happened only after 83 image captures (84th iteration in for loop) and hence i felt there is huge memory leak.

    Not sure this is optimistic solution for this problem. But I managed to solve using below steps..

    (1) renderInContext: is not releasing the graphics context immediately and hence accumulating memory and hence low memory warnings. Solution i tried is keep the entire function under @autorelease and just delay capturing next image by 1 millisecond which is negligible in terms of performance.

    (2) Avoided using forloop and storing images in a mutable array. This also saved some memory. This reduces heap memory usage as well.

    Hope this helps somebody..