頭を壁にぶつけて眠れぬ夜を過ごした数日後、ここで助けを見つけたいと思っています。ここでさまざまな投稿を行いましたが、どの回答も解決策を提供していないようです。
要するに、私の問題は、UIWebView を頻繁に (10 分以上) 使用した後にアプリがクラッシュすることです (たとえば、大きなニュース ペーパー サイトを連続して開くなど)。
詳細を説明するには: iPhone アプリを作成していて、MainViewController から、navigationController に browserViewController をプッシュします。browserViewController は、UWebView を含む nib をロードします (プログラムで WebView を作成しません)。UIWebView は、Interface Builder を使用して接続されています。
Main に戻ってから browserViewController に戻ると、nil の場合のみ browserViewController を再作成します。(UIWebViewにロードされたコンテンツを保持したい-メモリ警告がある場合のみ、このビューをアンロードし、使用されているすべてのメモリを解放する必要があります)。
MainViewController と browserViewController の両方で、メモリ警告に応答していますが、これでは十分な緩和が得られないようです。
Instruments を見ると、たとえば CFData(store) が増加し続けていることに気付きました。また、メモリ警告をシミュレートして (以下のコードを参照)、browserViewController で viewDidUnload を呼び出しても、CFData は割り当てられたままになり、解放されません。
だから私の最大の質問は
、「ブラウジング」から作成されたメモリを解放する方法は?
これは 2 つのケース
に当てはまります。
- ユーザーが 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 アプリケーションの DidFinishLaunching でもこれを使用しました)。
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]; [NSURLCache setSharedURLCache:sharedCache]; [sharedCache release];
残念ながら、これはどれも「キャッシュをクリア」したり、CFData(store) によって割り当てられたメモリを解放したりするのに役立ちませんでした。
誰かがこれに光を当てて、私が見逃していることや間違っていることを教えてくれれば、私はこれを大いに感謝します.
.
.
編集:
KiwiBastard からの最初の返信の後、Instruments で観察したことを示すスクリーン ショットを追加しました。
.
.
2010年6月から編集:
私はまだこれを解決できていません。
2 回目の試行では、UIWebView を完全にプログラムで作成しました。
まだ同じ問題。しかし、私は奇妙な行動に気づきました。たとえば、PDF ドキュメントを webView にロードし、PDF ページを上下にスクロールしないと、webView とデータが正常に解放されます。ただし、2 番目のページにスクロールするとすぐに、dealloc が機能しなくなり、ある時点でアプリのメモリが不足してしまいます。これはまったく奇妙で、解決できません。
誰でもアイデアはありますか?ヘルプ?