9

現在、ARC を使用する iOS 5.1 でナビゲーション コントローラー アプリを作成しています。私はしばしば Web ページを表示する必要があり、側面にいくつかのカスタム コンテンツを持つ単なる UIWebView である Web ビューアーを作成しました。ユーザーがページを見終わったら、戻るボタンを押します。これにより、カスタム Web ビューアに関連付けられているすべてのメモリが解放されます。私の問題は、戻るボタンを押してもすべてのメモリが解放されないように見えることです。私は、異なるページを呼び出す最初のレスポンダーを持つボタンのほんの数個であるおもちゃのアプリ(github )を作成しました。

@implementation ViewController
-(IBAction)googlePressed:(id)sender
{
   CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.google.com"];
   [self.navigationController pushViewController:customWebView animated:NO];
 }
-(IBAction)ksbwPressed:(id)sender
{
   CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.ksbw.com/news/money/Yahoo-laying-off-2-000-workers-in-latest-purge/-/1850/10207484/-/oeyufvz/-/index.html"];
   [self.navigationController pushViewController:customWebView animated:NO];
}
-(IBAction)feedProxyPressed:(id)sender
{
   CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://feedproxy.google.com/~r/spaceheadlines/~3/kbL0jv9rbsg/15159-dallas-tornadoes-satellite-image.html"];
   [self.navigationController pushViewController:customWebView animated:NO];
}
-(IBAction)cnnPressed:(id)sender
{
   CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.cnn.com/2012/04/04/us/california-shooting/index.html?eref=rss_mostpopular"];
   [self.navigationController pushViewController:customWebView animated:NO];
}

CustomWebView は、IB で UIWebView プロパティにリンクされた単なる UIWebView です。

@implementation CustomWebView

@synthesize webView, link;

- (id)initWithStringURL:(NSString *) stringURL
{
   if (self = [super init]) {
       link = stringURL;
   } 
   return self;
}


- (void)viewDidLoad
{
   [super viewDidLoad];
   NSURL *url = [NSURL URLWithString:link];
   NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
   [webView loadRequest:urlRequest];
}

- (void)viewDidUnload
{
   [super viewDidUnload];
}

私の問題は、すべてがロードされたら、ヒープのベースラインを最初の ViewController に設定することです。次に、ページを読み込んで ViewController に戻った後にヒープをチェックし、次のヒープショットを取得します。

ヒープショット

これは、一連のボタンをクリックして ViewController に戻るたびに、CustomWebView をすべて解放する必要があるにもかかわらず、ヒープが成長し続けることを示しています。

編集:

上記のサンプル プロジェクトはgithubにあります。

4

6 に答える 6

8

私は同じような問題を抱えていました、私はこの小さな魔法のかけらを見つけました

/*

 There are several theories and rumors about UIWebView memory leaks, and how
 to properly handle cleaning a UIWebView instance up before deallocation. This
 method implements several of those recommendations.

 #1: Various developers believe UIWebView may not properly throw away child
 objects & views without forcing the UIWebView to load empty content before
 dealloc.

 Source: http://stackoverflow.com/questions/648396/does-uiwebview-leak-memory

 */        
[webView loadHTMLString:@"" baseURL:nil];

/*

 #2: Others claim that UIWebView's will leak if they are loading content
 during dealloc.

 Source: http://stackoverflow.com/questions/6124020/uiwebview-leaking

 */
[webView stopLoading];

/*

 #3: Apple recommends setting the delegate to nil before deallocation:
 "Important: Before releasing an instance of UIWebView for which you have set
 a delegate, you must first set the UIWebView delegate property to nil before
 disposing of the UIWebView instance. This can be done, for example, in the
 dealloc method where you dispose of the UIWebView."

 Source: UIWebViewDelegate class reference    

 */
[webView setDelegate:nil];


/*

 #4: If you're creating multiple child views for any given view, and you're
 trying to deallocate an old child, that child is pointed to by the parent
 view, and won't actually deallocate until that parent view dissapears. This
 call below ensures that you are not creating many child views that will hang
 around until the parent view is deallocated.
 */

[webView removeFromSuperview];
于 2012-07-17T11:37:32.250 に答える
1

UIWebViewはメモリピッグであり、メモリの割り当てを適切に解除しません。CustomWebViewクラスに-(void)dealloc呼び出しを入れました。これは、[戻る]ボタンが押されたときに期待どおりに呼び出されます。

[[NSURLCache sharedURLCache] removeAllCachedResponses]を試すか、NSURLCacheの独自のコピーを使用して解放することができますが、率直に言って、UIWebViewはそれ自体を完全にクリーンアップすることはありません。

于 2012-04-15T13:30:51.483 に答える
1

私はしばらくARCを使用してきましたが、過去に、何か他のものをロードするように指示されるまで、Webビューがロードされたものを保持することがわかりました。私がこれを回避する方法は、ビューでjavascript呼び出しを使用することです(またはDid)が次のように消えます:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.webView loadHTMLString:@"<html></html>" baseURL:nil];
}

これは私の記憶を解放します。

于 2012-04-11T20:27:24.497 に答える
0

ブレンダンのいくつかのポイント:

何が起こっているのかを確認するのに十分なコードを投稿していません。しかし、コントローラーが単一の UIWebView を所有し、ボタンを押すたびに別の UIWebView を作成するのではなく、単に関連する URL を含む文字列を渡すのはなぜでしょうか? これは、周囲に 1 つしかないことを保証する、より優れた設計パターンです。

于 2012-04-11T13:23:00.160 に答える
0

私はまだ ARC を使用していませんが、あなたのカスタム webview コードを見ると、あなたが作成した webview はまだ生きていると思います。

WebView が適切に強制終了されることを確認したい場合は、viewWill/DidDisappear で [webview stopLoading] を呼び出し、WebView を nil するようにしてください。

(注意: 別のビューをプッシュすると、webview も強制終了されるため、これらの問題を適切に処理するようにしてください)

ほとんどの場合、viewController をポップした後でも、webView デリゲート メソッドへのコールバックによってアプリがクラッシュする問題が webViews で発生しました。(ARCがクラッシュを防いでいると思います)。

これが役立つかどうか教えてください。

于 2012-04-09T23:01:28.403 に答える