经过数天将我的头撞在墙上并度过了不眠之夜后,我希望在这里找到一些帮助。我在这里浏览了各种帖子,但是似乎没有答案可以为我提供解决方案。

简而言之,我的问题是我的应用在UIWebView的大量使用(> 10分钟)后崩溃(例如,依次打开较大的新闻纸网站-一个接一个)。

详细说明:
我正在编写一个iPhone应用程序,并从MainViewController推送了一个NavigationController上的browserViewController。 browserViewController加载一个包含UWebView的 Nib (我不以编程方式创建WebView)。 UIWebView使用Interface Builder进行了连接。

当回到Main,然后再回到browserViewController时,如果它为nil,我只会重新创建browserViewController。 (我想保留在UIWebView中加载的内容-仅在出现内存警告时应卸载此 View 并释放所有已使用的内存)。

在MainViewController和browserViewController中,我都响应内存警告,但这似乎不能提供足够的缓解。

在查看Instruments时,我注意到例如CFData(store)不断增加。即使我模拟了内存警告(请参见下面的代码)并在browserViewController上调用viewDidUnload,CFData仍会分配并且不会被释放。

所以我最大的问题是:
如何释放通过“浏览”创建的内存?

这有两种情况:
-如何确保viewDidUnload正确释放分配给CFData(store)的内存?
-当用户继续在browserViewController中加载页面时,如何释放内存?

谁管理CFData?

请参阅下面的简化示例代码:

MainViewController.h

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

@interface MainViewController : UIViewController {
    BrowserViewController *browViewController;
}

- (void) switchToBrowserViewController;

@end

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

#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
#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

我尝试了其他职位的各种建议。例如:
  • 1)将一个空白页面加载到WebView中。
        NSString *html = @"<html><head></head><body></body></html>";
        [browserWebView loadHTMLString:html baseURL:nil];
    
  • 2)在上述代码的各个位置使用removeAllCachedResponses
        [[NSURLCache sharedURLCache] removeAllCachedResponses];
    
  • 3)setSharedURLCache也没有提供缓解(我还在AppDelegate applicationDidFinishLaunching中使用了此功能)。
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
        [NSURLCache setSharedURLCache:sharedCache];
        [sharedCache release];
    

  • 不幸的是,这些都没有帮助“清除缓存”或释放CFData(store)分配的内存。

    如果有人能对此有所启发,让我知道我的缺失或做错了,我将不胜感激。




    编辑:
    在收到KiwiBastard的初步答复后,我添加了一个屏幕截图,显示了我在Instruments中观察到的内容:




    ,从2010年6月开始编辑:
    我仍然无法解决这个问题。
    在第二次尝试中,我完全以编程方式创建了UIWebView。
    还是同样的问题。但是我注意到一个奇怪的行为。例如,如果我将PDF文档加载到webView中,而没有向上或向下滚动PDF页面,则webView&数据将成功发布。但是,一旦我滚动到第二页,该dealloc将不再起作用,并且我的App有时会耗尽内存。这完全是奇怪的,我无法解决。
    有人知道吗?帮助?

    最佳答案

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

    09-18 23:26