3

I have checked all related questions and answers both on Stackoverflow and internet but i came to no conclusion. I am developing an ipad app, and what it does is making request to my web server download pdf file as NSData and showing it in UIWebView. The problem is even though the app(closes) segues from pdfviewer to mainviewcontroller, memory is not released thus increasing memory usage all the time. It starts with 14 mb and then every time i segue to pdfviewer from main controller it adds up. Since i'm using arc i can't release it. I am also clearing cache.

The Mainview controller.m

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"showpdf"]){
        PdfViewer *pdfviewer=(PdfViewer*)[segue destinationViewController];
        pdfviewer.ReportID=TheReportID;
        pdfviewer.TabID=_TabID;
    }

}

PdfViewer.h

@property (strong, nonatomic) IBOutlet UIWebView *MainWebView;

PdfViewer.m

-(void)viewDidLoad
   {    
      NSURL *url = [NSURL fileURLWithPath:filePath];
      NSURLRequest *request = [NSURLRequest requestWithURL:url];
      [_MainWebView loadRequest:request];
   }

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    if([segue.identifier isEqualToString:@"ShowMain5"]){
        MainViewController *mv=(MainViewController*)[segue destinationViewController];
        mv.TabID=_TabID;
    }

}
-(void)dealloc{
   NSLog(@"test");
}

i also tried to add UIWebview programmatically instead of IBoutlet but still couldn't solve the problem.

Programmatically( alternative )

 @implementation PdfViewer

    UIWebView *webview;

    - (void)viewDidLoad
    {    
       webview=[[UIWebView alloc]initWithFrame:CGRectMake(35, 35, 768,959)];
       [webview loadRequest:request];
       [self.view addSubview:webview];
    }

When user press back button all i do is go back to mainviewcontroller modally.All segues are modal FYI.

As i understood that pdfviewer is not calling dealloc when it segues back to mainviewcontroller i checked if anyone had similar issue with viewcontrollers before and i found this question UIViewController -dealloc method not called now i think memory stays at the same level, but now it gives pdfviewer is not in the window hierarchy error.

Community
  • 1
  • 1
Codette
  • 1,007
  • 2
  • 9
  • 18

3 Answers3

2

For my experience with UIWebView[s] the solution was to have a singleton instance for it, so at least this basic interface and properties

 // MXMWebView.h
 @interface MXMWebView : NSObject <UIWebViewDelegate, UIScrollViewDelegate> {

  }

  + (instancetype)sharedInstance;

  @property(nonatomic, strong) UIWebView *webView;

and

 //MXMWebView.m
  @implementation MXMWebView

  @synthesize webView;
  @synthesize delegate;

  #pragma mark - Singleton Methods

  + (instancetype)sharedInstance {
     static id _sharedInstance = nil;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
          _sharedInstance = [[self alloc] init];
     });

   return _sharedInstance;

}

loretoparisi
  • 15,724
  • 11
  • 102
  • 146
  • my method that i just mentioned below only limits the usage of uiwebview but it doesn't decrease the memory usage after 25mb.Normally when program starts it uses 15mb and then when i open pdfviewer controller it goes to 25mb then stays between 25mb and 32 mb. Your method might work better, i will tell the results after i test it.Thanks – Codette Sep 24 '14 at 09:02
  • 1
    I think it could improve performances, considering that my app has 3 UIWebView always running as singleton, with html and javascript preloaded (just after app startup I preload everything that must be in HTML like the page javascript, css etc. – loretoparisi Sep 24 '14 at 10:23
  • and how much extra ram usage does it after, say , you load a pdf with 1.4mb and then remove it? i don't know where i've read it but i think javascript and other engines to show pdf takes most of the memory to show it and then they are not deallocated even though you close the wievcontroller. – Codette Sep 24 '14 at 10:27
  • 1
    this is a good point. If you have javascript code to be allocated once since it's used more than one time you will get best performances with the singleton instance. If you javascript code allocates memory such as showing a canvas or loading a PDF, then you need to deallocate the JavaScript engine forcing the garbage collector to be called. Which PDF engine is that? – loretoparisi Sep 24 '14 at 20:11
1

As i understood that pdfviewer is not calling dealloc when it segues back to mainviewcontroller. i checked if anyone had similar issue with viewcontrollers before and i found this question UIViewController -dealloc method not called. So i added

-(void)viewDidAppear:(BOOL)animated{
   [super viewDidAppear:animated];
   self.view.window.rootViewController=self;
}

to both mainviewcontroller.m and pdfviewer.m and also

-(void)dealloc{

     [_MainWebView loadHTMLString:@"" baseURL:nil];
     [_MainWebView stopLoading];
     [_MainWebView setDelegate:nil];
     [_MainWebView removeFromSuperview];

    [[NSURLCache sharedURLCache]removeAllCachedResponses];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    [[NSURLCache sharedURLCache] setMemoryCapacity:0];

}

method to pdfViewer.m and it solved the problem.Thanks everyone for their contribution.

Community
  • 1
  • 1
Codette
  • 1,007
  • 2
  • 9
  • 18
  • When i open Pdfviewer from mainviewcontroller it loads the view in to the memory and when i segue back to mainviewcontroller it doesn't dealloc pdfviewer because it is not the rootviewcontroller. I think i must add the information that i don't use navigationcontroller so i just segue from one viewcontroller to another without clearing anything. I think that was the problem.Know memory usage doesnt pass 30mb at all.But i'm not sure if this method has any drawbacks so i won't close the question yet. – Codette Sep 24 '14 at 09:00
0

Set webview delegate to nil while segues from pdfviewer to mainviewcontroller

[_MainWebView setDelegate:nil];

--- edit

[_MainWebView removeFromSuperView];