簡體   English   中英

UIWebView-CFData何時(或如何)發布?

[英]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

//  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對象名稱

我認為可能發生的事情是您的瀏覽器從未被釋放,而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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM