【问题标题】:UIWebView doesn't free memoryUIWebView 不会释放内存
【发布时间】:2014-11-17 22:44:10
【问题描述】:

我已经在 Stackoverflow 和互联网上检查了所有相关的问题和答案,但我没有得出任何结论。我正在开发一个 ipad 应用程序,它的作用是向我的网络服务器发出请求,将 pdf 文件作为 NSData 下载并在 UIWebView 中显示。问题是即使应用程序(关闭)从 pdfviewer 切换到 mainviewcontroller,内存也不会释放,因此一直在增加内存使用量。它从 14 mb 开始,然后每次我从主控制器转到 pdfviewer 时,它都会加起来。由于我使用的是 arc,我无法释放它。我也在清缓存。

主视图控制器.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");
}

我还尝试以编程方式添加 UIWebview 而不是 IBoutlet,但仍然无法解决问题。

以编程方式(替代)

 @implementation PdfViewer

    UIWebView *webview;

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

当用户按下后退按钮时,我所做的只是模态地返回主视图控制器。所有 segues 都是模态的,仅供参考。

据我了解,当 pdfviewer 回到 mainviewcontroller 时,它没有调用 dealloc pdfviewer 不在窗口层次结构错误。

【问题讨论】:

  • _MainWebView 是如何定义的以及指向它的指针如何
  • 我编辑了问题,它被定义为强 IBoutlet,现在它很弱。我还尝试以编程方式添加它,以便我可以解除分配并将其从内存中删除,但它不起作用。
  • 在PdfViewController中实现一个带有NSLog的dealloc方法,看看是否被调用
  • 它没有被调用。
  • 我解决了,谢谢你的帮助。 @Daij-Djan 你的问题让我找到了答案

标签: ios objective-c iphone ipad uiwebview


【解决方案1】:

在从 pdfviewer 切换到 mainviewcontroller 时将 webview 委托设置为 nil

[_MainWebView setDelegate:nil];

---编辑

[_MainWebView removeFromSuperView];

【讨论】:

  • 我担心没用。委托不牢固,因此此处不会有保留周期。如果它很强大,那你是对的
  • 是什么让您认为将代理设置为 nil 会有所帮助?
【解决方案2】:

根据我对 UIWebView[s] 的经验,解决方案是为其创建一个单例实例,因此至少要有这个基本接口和属性

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

  }

  + (instancetype)sharedInstance;

  @property(nonatomic, strong) UIWebView *webView;

 //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;

}

【讨论】:

  • 我刚刚在下面提到的方法只限制了 uiwebview 的使用,但它不会减少 25mb 之后的内存使用量。通常当程序启动时它使用 15mb,然后当我打开 pdfviewer 控制器时它会转到25mb 然后保持在 25mb 和 32mb 之间。您的方法可能会更好,我会在测试后告诉结果。谢谢
  • 我认为它可以提高性能,考虑到我的应用程序有 3 个 UIWebView 始终作为单例运行,并预加载了 html 和 javascript(就在应用程序启动后,我预加载了必须在 HTML 中的所有内容,例如页面 javascript, CSS等
  • 在你加载一个 1.4mb 的 pdf 然后删除它之后,它会额外使用多少内存?我不知道我在哪里读过它,但我认为显示 pdf 的 javascript 和其他引擎会占用大部分内存来显示它,然后即使您关闭 wievcontroller,它们也不会被释放。
  • 这是一个很好的观点。如果您要分配一次 javascript 代码,因为它被使用了不止一次,那么您将在单例实例中获得最佳性能。如果您的 javascript 代码分配内存(例如显示画布或加载 PDF),那么您需要解除分配 JavaScript 引擎以强制调用垃圾收集器。那是哪个 PDF 引擎?
【解决方案3】:

据我了解,当 pdfviewer 转回 mainviewcontroller 时,它不会调用 dealloc。我之前检查过是否有人对视图控制器有类似的问题,我发现了这个问题UIViewController -dealloc method not called。所以我加了

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

到 mainviewcontroller.m 和 pdfviewer.m 以及

-(void)dealloc{

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

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

}

pdfViewer.m 的方法,它解决了问题。感谢大家的贡献。

【讨论】:

  • 当我从 mainviewcontroller 打开 Pdfviewer 时,它会将视图加载到内存中,当我重新回到 mainviewcontroller 时,它不会释放 pdfviewer,因为它不是 rootviewcontroller。我想我必须添加我不使用导航控制器的信息,所以我只是从一个视图控制器到另一个视图控制器而不清除任何东西。我认为这是问题所在。知道内存使用量根本不会超过 30mb。但我不确定这种方法是否有任何缺点,所以我不会关闭这个问题。
猜你喜欢
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-31
  • 2011-01-12
  • 2016-10-01
  • 2012-03-15
  • 1970-01-01
  • 2013-12-12
相关资源
最近更新 更多