简体   繁体   English

UIWebView-CFData何时(或如何)发布?

[英]UIWebView - When (or how) does CFData get released?

after multiple days of banging my head against the wall and having sleepless nights I'm hoping to find some help here. 经过数天将我的头撞到墙上并度过了不眠之夜后,我希望在这里找到一些帮助。 I've gone through various posts here, but none of the answers seem to provide a resolution for me. 我在这里浏览了各种帖子,但是似乎没有答案为我提供解决方案。

In short, my problem is that my App crashes after heavy usage (>10min) of the UIWebView (eg opening larger news paper sites in series - one after the other). 简而言之,我的问题是我的应用程序在大量使用(> 10分钟)UIWebView之后崩溃(例如,依次打开较大的新闻纸网站-一个接一个)。

To give more details: I am writing an iPhone App and from the MainViewController I push a browserViewController on the navigationController. 要提供更多详细信息:我正在编写iPhone应用程序,并从MainViewController中将browserViewController推入navigationController上。 The browserViewController loads a nib which contains a UWebView (I do not create the WebView programatically). browserViewController加载一个包含UWebView的笔尖(我没有以编程方式创建WebView)。 The UIWebView is wired up using Interface Builder. UIWebView使用Interface Builder进行了连接。

When going back to Main and then going again to the browserViewController, I only recreate the browserViewController if it is nil. 当回到Main,然后再回到browserViewController时,我只会在null时重新创建browserViewController。 (I want to keep the content that is loaded i the UIWebView - only if there is a memory warning shoud this view be unloaded and release all memory used). (我想保留在UIWebView中加载的内容-仅在出现内存警告时应卸载此视图并释放所有已使用的内存)。

In both, MainViewController and browserViewController I am responding to memory warnings, but this seems not to provide enough relief. 在MainViewController和browserViewController中,我都响应内存警告,但这似乎不能提供足够的缓解。

Looking at Instruments I noticed that for example CFData(store) keeps increasing. 在查看工具时,我注意到例如CFData(store)不断增加。 And even if I simulate a memory warning (see code below) and call viewDidUnload on browserViewController, CFData remains allocated and does not get freed. 即使我模拟了内存警告(请参见下面的代码)并在browserViewController上调用viewDidUnload,CFData仍会分配并且不会被释放。

So my biggest question is: 所以我最大的问题是:
How to free up memory created from "browsing"? 如何释放从“浏览”创建的内存?

This counts for two cases: 这有两种情况:
- how do I make sure that viewDidUnload properly frees memory allocated my CFData(store)? -如何确保viewDidUnload正确释放分配给CFData(store)的内存?
- how to free up memory when the user keeps loading pages in browserViewController? 用户继续在browserViewController中加载页面时如何释放内存?
.
Who manages CFData? 谁管理CFData?

See below for my simplified sample code: 请参阅下面的简化示例代码:

MainViewController.h MainViewController.h

//  MainViewController.h
#import "myAppDelegate.h"
#import "BrowserViewController.h"

@interface MainViewController : UIViewController {
    BrowserViewController *browViewController;
}

- (void) switchToBrowserViewController;

@end

MainViewController.m MainViewController.m

//  MainViewController.m
#import "MainViewController.h"

@implementation MainViewController

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    [browViewController release];
    browViewController = nil;
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)dealloc {
    [browViewController release];
    browViewController = nil;
    [super dealloc];
}

- (void) switchToBrowserViewController {

    // create new browViewController if needed
    if ( browViewController == nil ) {
        browViewController = [[BrowserViewController alloc]     initWithNibName:@"BrowserViewController" bundle:nil];
    }

    browViewController.navigationItem.hidesBackButton = YES;

    [((myAppDelegate *)[UIApplication sharedApplication].delegate).navController setNavigationBarHidden:YES animated:NO];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration: 1];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:
  ((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController.view cache:YES];

    [((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController pushViewController:browViewController animated:NO];
    [UIView commitAnimations];

}

@end

BrowserViewController.h BrowserViewController.h

//  BrowserViewController.h

#import <UIKit/UIKit.h>
#import "myAppDelegate.h"

@interface BrowserViewController : UIViewController <UIWebViewDelegate> {
    IBOutlet UITextField *browserURLField;
    IBOutlet UIWebView *browserWebView;
}

@property (nonatomic, retain) UIWebView *browserWebView;

- (void) loadURLinBrowser;

@end

BrowserViewController.m BrowserViewController.m

//  BrowserViewController.m
#import "BrowserViewController.h"

@implementation BrowserViewController
@synthesize browserWebView;

- (void)viewDidLoad {
    [browserWebView setDelegate:self];
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload { 
    [super viewDidUnload];

    [browserWebView stopLoading];
    [browserWebView setDelegate:nil];
    [browserWebView removeFromSuperview];
    [browserWebView release];
    browserWebView = nil;

    browserURLField = nil;
}

- (void)dealloc {
    [browserURLField release];

    browserWebView.delegate = nil;
    [browserWebView stopLoading];
    browserWebView = nil;
    [browserWebView release];

    [super dealloc];
}

- (void) switchBackToMainViewController {

    [((myAppDelegate *)[UIApplication sharedApplication].delegate).navController setNavigationBarHidden:NO animated:NO];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration: 1];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController.view cache:YES];

    [((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController popViewControllerAnimated:NO];

    [UIView commitAnimations];
}

- (void) loadURLinBrowser {
    NSURL *url = [[NSURL alloc] initWithString:browserURLField.text];
    NSMutableURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
    [browserWebView loadRequest: request];
    [request release];
    [url release];
}

@end

I have tried various recommendations from other posts. 我尝试了其他职位的各种建议。 For example: 例如:

  • 1) Loading an empty page into the WebView. 1)将一个空白页加载到WebView中。

      NSString *html = @"<html><head></head><body></body></html>"; [browserWebView loadHTMLString:html baseURL:nil]; 
  • 2) using removeAllCachedResponses on various places in the above code 2)在上面的代码中的各个位置使用removeAllCachedResponses

      [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
  • 3) setSharedURLCache did also not provide relief ( I also used this in the AppDelegate applicationDidFinishLaunching). 3)setSharedURLCache也没有提供缓解(我还在AppDelegate applicationDidFinishLaunching中使用了此功能)。

      NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]; [NSURLCache setSharedURLCache:sharedCache]; [sharedCache release]; 

Unfortunately none of this has helped to "clear the cache" or to free memory allocated by CFData(store). 不幸的是,这些都没有帮助“清除缓存”或释放CFData(store)分配的内存。

If anyone could shine some light on this and let me know what I'm missing or doing wrong I would greatly appreciate this. 如果有人能对此有所启发,让我知道我的缺失或做错了,我将不胜感激。

.
.

Edit: 编辑:
After the initial reply from KiwiBastard I added a screen shot that shows what I observe in Instruments: 在收到KiwiBastard的初步答复后,我添加了一个屏幕截图,显示了我在Instruments中观察到的内容:

在此处输入图片说明

.
.

Edit from June 2010: 从2010年6月开始编辑:
I have still not been able to solve this. 我仍然无法解决这个问题。
In a second attempt, I created the UIWebView completely programmatically. 在第二次尝试中,我完全以编程方式创建了UIWebView。
Still same issue. 还是同样的问题。 However I noticed a strange behavior. 但是我注意到一个奇怪的行为。 If I load for example a PDF document into the webView and I do not scroll the PDF page up or down, the webView & data gets successfully released. 例如,如果我将PDF文档加载到webView中,而没有向上或向下滚动PDF页面,则webView&数据将成功发布。 However as soon as I scroll to the second page, the dealloc won't work any longer and my App ends up running out of memory at some point. 但是,一旦我滚动到第二页,该dealloc将不再起作用,并且我的App有时会耗尽内存。 This is totally strange and I cannot get this resolved. 这完全是奇怪的,我无法解决。
Anyone any idea? 有人知道吗? Help? 救命?

要释放CFData,您只需调用CFRelease( 您的CFData对象名称

I think what could be happening is that your Browser is never deallocated, and the viewDidUnload is probably never being called. 我认为可能发生的事情是您的浏览器从未被释放,而viewDidUnload可能从未被调用。

Because your MainViewController has a variable of type BrowserViewController that is never released, that will be resident for the life of your app. 由于您的MainViewController具有一个类型为BrowserViewController的变量,该变量从未发布,因此将在您的应用程序生命周期内永久存在。 Also because you are only switching views, the view will stay in memory too. 另外,由于仅切换视图,因此视图也将保留在内存中。

Can I suggest you try creating the BrowserViewController variable when you need it, and release it once it has been pushed by the navcontroller eg 我是否可以建议您在需要时尝试创建BrowserViewController变量,并在navcontroller将其推送后将其释放,例如

 BrowserViewController *browViewController = [[BrowserViewController alloc]     initWithNibName:@"BrowserViewController" bundle:nil];

 browViewController.navigationItem.hidesBackButton = YES;

 [((myAppDelegate *)[UIApplication sharedApplication].delegate).navController setNavigationBarHidden:YES animated:NO];

 [UIView beginAnimations:nil context:NULL];
 [UIView setAnimationDuration: 1];
 [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:
  ((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController.view cache:YES];

 [((myAppAppDelegate *)[UIApplication sharedApplication].delegate).navController pushViewController:browViewController animated:NO];
 [UIView commitAnimations];
 [browViewController release];

I know that it will slightly effect performance because it has to load the nib everytime, but you distinctly don't want to cache the vc anyway? 我知道这会稍微影响性能,因为它每次都必须加载笔尖,但是您显然不想缓存vc吗?

Somewhere I read, this is a well known bug with UIWebView. 在我读过的某个地方,这是UIWebView的一个众所周知的错误。 Some says to use a static webview object to avoid initializing it again and again but couldn't find a proper solution. 有人说使用静态的webview对象来避免一次又一次地初始化它,但是找不到合适的解决方案。 Even you follows the same approach. 即使您遵循相同的方法。 Luckily my requirement was a plain web view with an image. 幸运的是,我的要求是带有图像的纯Web视图。 So I ended up using a custom controller with a UIImageView and a UITextView without editing. 因此,我最终使用了带有UIImageView和UITextView的自定义控制器,而没有进行编辑。 Works fine for me. 对我来说很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM