[英]UIWebView - When (or how) does CFData get released?
經過數天將我的頭撞到牆上並度過了不眠之夜后,我希望在這里找到一些幫助。 我在這里瀏覽了各種帖子,但是似乎沒有答案為我提供解決方案。
簡而言之,我的問題是我的應用程序在大量使用(> 10分鍾)UIWebView之后崩潰(例如,依次打開較大的新聞紙網站-一個接一個)。
要提供更多詳細信息:我正在編寫iPhone應用程序,並從MainViewController中將browserViewController推入navigationController上。 browserViewController加載一個包含UWebView的筆尖(我沒有以編程方式創建WebView)。 UIWebView使用Interface Builder進行了連接。
當回到Main,然后再回到browserViewController時,我只會在null時重新創建browserViewController。 (我想保留在UIWebView中加載的內容-僅在出現內存警告時應卸載此視圖並釋放所有已使用的內存)。
在MainViewController和browserViewController中,我都響應內存警告,但這似乎不能提供足夠的緩解。
在查看工具時,我注意到例如CFData(store)不斷增加。 即使我模擬了內存警告(請參見下面的代碼)並在browserViewController上調用viewDidUnload,CFData仍會分配並且不會被釋放。
所以我最大的問題是:
如何釋放從“瀏覽”創建的內存?
這有兩種情況:
-如何確保viewDidUnload正確釋放分配給CFData(store)的內存?
用戶繼續在browserViewController中加載頁面時如何釋放內存?
。
誰管理CFData?
請參閱下面的簡化示例代碼:
// MainViewController.h
#import "myAppDelegate.h"
#import "BrowserViewController.h"
@interface MainViewController : UIViewController {
BrowserViewController *browViewController;
}
- (void) switchToBrowserViewController;
@end
// 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
#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
#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對象名稱 ) 。
我認為可能發生的事情是您的瀏覽器從未被釋放,而viewDidUnload可能從未被調用。
由於您的MainViewController具有一個類型為BrowserViewController的變量,該變量從未發布,因此將在您的應用程序生命周期內永久存在。 另外,由於僅切換視圖,因此視圖也將保留在內存中。
我是否可以建議您在需要時嘗試創建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];
我知道這會稍微影響性能,因為它每次都必須加載筆尖,但是您顯然不想緩存vc嗎?
在我讀過的某個地方,這是UIWebView的一個眾所周知的錯誤。 有人說使用靜態的webview對象來避免一次又一次地初始化它,但是找不到合適的解決方案。 即使您遵循相同的方法。 幸運的是,我的要求是帶有圖像的純Web視圖。 因此,我最終使用了帶有UIImageView和UITextView的自定義控制器,而沒有進行編輯。 對我來說很好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.