-deallocではなく-(void)viewDidUnloadでオブジェクトを解放する必要があるのはいつですか?


回答:


51

すでに示されていることに加えて、私は背後にあるロジックについてさらに詳しく説明したいと思いました-viewDidUnload

これを実装する最も重要な理由の1つは、UIViewControllerサブクラスには通常、ビュー階層内のさまざまなサブビューへの所有参照も含まれていることです。これらのプロパティは、たとえばIBOutletsnibからロードするとき、またはの内部-loadViewでプログラムによって設定されている可能性があります。

サブビューの追加の所有権。これはUIViewController、ビューがビュー階層から削除され、メモリを節約するために解放された場合でも、サブビューはビューによって解放されますが、サブビュー自体には未処理のサブビューがUIViewControllerまだ含まれているため、実際には割り当て解除されません。それらのオブジェクトへの参照も保持します。UIViewControllerこれらのオブジェクトの追加の所有権を解放することで、オブジェクトの割り当てが解除され、メモリが解放されます。

ここで解放したオブジェクトは、通常、UIViewControllerビューがre-loadedであるときに、ニブから、またはの実装を介して再作成および再設定され-loadViewます。

また、UIViewController viewプロパティはnil、このメソッドが呼び出された時点であることに注意してください。


1
ビュー/ビューコントローラのライフサイクルを理解するには、developer.apple.com /
library

21

などのドキュメントは言います

これは、ビューコントローラーがビューとそのビューに関連付けられているオブジェクトを解放してメモリを解放する必要があるメモリ不足状態のときに呼び出されます。

同じ状況dealloc呼び出されません。このメソッドは、OS3以降でのみ使用できます。iPhone OS 2.xで同じ状況に対処するのは本当に大変でした。

2015年7月更新viewDidUnload「メモリ不足の状態ではビューが削除されなくなったため、このメソッドが呼び出されない」ため、iOS 6では非推奨でした。だから、現代​​のアドバイスはそれを心配して使用しないことdeallocです。


6
また、ドキュメントから:「viewDidLoadメソッドまたはアプリケーションの他の部分から後で簡単に再作成できるオブジェクトに対してのみこれを行う必要があります。このメソッドを使用して、ユーザーデータやその他の情報を解放することはできません。簡単に再作成できます」。それは私自身も多かった質問です、ありがとう!
leolobato 2009

ビューが現在表示されている場合はどうなりますか?メモリ不足の警告のため、ドロップするのは悪いことではないでしょうか?;)その後、アプリは空白の空になります。メモリが少ないため、ビューを解放する意味がありません。ビューが表示されない場合は、常にコントローラー全体を解放します。Althogh私はそのままにして、その子ビューコントローラーのすべてのロード/アンロードを管理するルートビューコントローラーを持っています...
感謝

いいえ、あるビューを別のビューと交換するだけの場合は、これを使用しません。UINavigationControllerを使用してビューの「スタック」がある場合を考えてください。表示されるビューは1つだけであり、メモリ警告がある場合は、表示されていないビューをすべて解放できます。
スティーブンダーリントン

Thanksが指摘したように、現在表示されているビューでviewDidUnloadが呼び出されないようにするにはどうすればよいですか?
arielcamus 2010年

1
viewDidUnloadは、現在表示されているビューでは呼び出されず、表示されていないビューでのみ呼び出されます。
progrmr 2010年

9

これは、通常、@propertyas "(nonatomic, retain)"およびas自体を設定して、現在のオブジェクトを解放して引数を保持するために作成されるためです。

self.property = nil;

...次のように何かを行います:

[property release];
property = [nil retain];

したがって、1つの石で2羽の鳥を殺すことになります。メモリ管理(既存のオブジェクトを解放する)とポインタをnilに割り当てます(nilポインタにメッセージを送信するとnilが返されるため)。

お役に立てば幸いです。


8

viewDidUnloadはビューではなく、ビューコントローラ内のメソッドであることに注意してください。ビューの dealloc方法は時にビューのアンロードと呼ばれますが、ビューコントローラの deallocメソッドは、後になるまで呼び出されない場合があります。

メモリ不足の警告が表示され、ビューが表示されない場合、たとえば、UIImagePickerControllerを使用してユーザーに写真を撮らせたりすると、ビューがアンロードされ、その後再読み込みする必要があります。


それは理にかなっている。常にView Controller全体をドロップするとどうなりますか?それが私が実際にやっていることです。この場合、-viewDidUnloadをあまり処理する必要はありませんよね?ビューが表示されない場合は常にコントローラー全体をドロップするため、ビューのみをドロップする状況はありませんでした。
感謝

ビューが表示されているが、その上にImagePickerのようなフルスクリーンビューがある場合、ビューを計画していなくてもアンロードされる可能性があることを覚えておいてください。
David Maymudes 09

6

結論:

ビューコントローラーにはビュープロパティがあります。通常、ペン先またはコードの一部は、このビューに他のビューを追加します。これは、次のように-viewDidLoadメソッド内で頻繁に発生します。

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createManyViewsAndAddThemToSelfDotView];
}

さらに、nibファイルはボタンを作成し、それをビューコントローラーのビューに追加できます。

iPhone OS 2.2では、システムから-didReceiveMemoryWarningが呼び出されたときに、メモリを解放するために何かを解放する必要がありました。それが理にかなっている場合は、ビューコントローラ全体のビューを解放できます。または、メモリを大量に消費するコンテンツのみ。

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

現在、新しいOS 3.0には-viewDidUnloadメソッドがあり、メモリが不足しているためにビューがアンロードされたときにシステムから呼び出されます(私を修正してください:正確にいつ呼び出されますか?)

-viewDidUnloadは、ビューコントローラー自体とビューの両方が所有していたすべてのオブジェクトを解放するために使用されます。理由:ビューコントローラーがビューの子への参照(ボタンなど)を保持している場合、その保持カウントが1以上であるため、参照された子ビューは解放されません。-viewDidUnloadで解放された後、解放できます。メモリから。


1
ビュー内のremeberがself.button = nil;を実行するためにアンロードしましたが、[button release];ではありません。
mk12 09

6

AppleはviewWillUnloadを非推奨にしました。今では、オブジェクトを解放するためにdidReceiveMemoryWarningまたはdeallocを使用する必要があります。

iOS 6では、UIViewControllerのviewWillUnloadメソッドとviewDidUnloadメソッドが廃止されました。これらのメソッドを使用してデータを解放していた場合は、代わりにdidReceiveMemoryWarningメソッドを使用してください。このメソッドを使用して、ビューコントローラーのビューが使用されていない場合は、ビューへの参照を解放することもできます。これを行う前に、ビューがウィンドウ内にないことをテストする必要があります。


5

ビューコントローラーがナビゲーションコントローラースタックからポップされ、他の場所に保持されていない場合は、割り当てが解除され、viewDidUnloadの代わりにdeallocが呼び出されます。loadViewで作成したビューをdeallocで解放する必要がありますが、deallocが呼び出されるとすぐに変数が存在しないため、変数をnilに設定する必要はありません。


3

保持しているサブビューを解放できます。たとえば、loadViewメソッドで保持したUIImageViewや、そのUIImageViewにあったイメージを解放できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.