Swiftでの割り当て解除


145

ビューコントローラーの寿命の終わりにいくつかのクリーンアップ、つまりNSNotificationCenter通知を削除したいのですが。dealloc結果を実装すると、Swiftコンパイラエラーが発生します。

Cannot override 'dealloc' which has been marked unavailable

Swiftでオブジェクトの寿命の終わりにクリーンアップを実行するための好ましい方法は何ですか?

回答:


333
deinit {
    // perform the deinitialization
}

Swiftのドキュメントから:

クラスインスタンスが割り当て解除される直前にdeinitializerが呼び出されます。ininitializerがinitキーワードで書き込まれるのと同様に、deinitializerはdeinitキーワードで記述します。デイニシャライザは、クラスタイプでのみ使用できます。

通常、インスタンスの割り当てが解除されたときに手動でクリーンアップを実行する必要はありません。ただし、独自のリソースで作業している場合は、追加のクリーンアップを自分で実行する必要がある場合があります。たとえば、ファイルを開いてデータを書き込むカスタムクラスを作成する場合、クラスインスタンスの割り当てを解除する前にファイルを閉じる必要がある場合があります。


45
deinit {
    // perform the deinitialization
}

Swiftの「dealloc」の正解です。

ただし、iOS 9の新機能として、NSNotificationCenterをクリーンアップする必要がないことを指摘しておくとよいでしょう。

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notes

NSNotificationCenter

OS X 10.11およびiOS 9.0では、NSNotificationCenterおよびNSDistributedNotificationCenterは、割り当て解除された可能性がある登録オブザーバーに通知を送信しなくなりました。オブザーバーをゼロ化-弱い参照として保存できる場合、基礎となるストレージはオブザーバーをゼロ化する弱い参照として保存します。オブジェクトが弱い保存ができない場合(つまり、ランタイムを妨げるカスタムの保持/解放メカニズムがある場合)オブジェクトを弱く保存できないため)、オブジェクトを非弱いゼロ化参照として保存します。これは、オブザーバーが割り当て解除メソッドで登録を解除する必要がないことを意味します。そのオブザーバーにルーティングされる次の通知は、ゼロ化された参照を検出し、オブザーバーの登録を自動的に解除します。オブジェクトを弱く参照できる場合、割り当て解除中に通知がオブザーバーに送信されなくなります。dealloc中に通知を受信するという以前の動作は、弱くないゼロの参照オブザーバーの場合でも存在します。-[NSNotificationCenter addObserverForName:object:queue:usingBlock]メソッドを介したブロックベースのオブザーバーは、システムがこれらのオブザーバーへの強い参照を保持しているため、使用されなくなった場合でも登録解除する必要があります。オブザーバー(弱参照またはゼロ参照のいずれか)を時期尚早に削除することは引き続きサポートされています。CFNotificationCenterAddObserverは、オブザーバーがオブジェクトではない可能性があるため、この動作に準拠していません。-[NSNotificationCenter addObserverForName:object:queue:usingBlock]メソッドを介したブロックベースのオブザーバーは、システムがこれらのオブザーバーへの強い参照を保持しているため、使用されなくなった場合でも登録解除する必要があります。オブザーバー(弱参照またはゼロ参照のいずれか)を時期尚早に削除することは引き続きサポートされています。CFNotificationCenterAddObserverは、オブザーバーがオブジェクトではない可能性があるため、この動作に準拠していません。-[NSNotificationCenter addObserverForName:object:queue:usingBlock]メソッドを介したブロックベースのオブザーバーは、システムがこれらのオブザーバーへの強い参照を保持しているため、使用されなくなった場合でも登録解除する必要があります。オブザーバー(弱参照またはゼロ参照のいずれか)を時期尚早に削除することは引き続きサポートされています。CFNotificationCenterAddObserverは、オブザーバーがオブジェクトではない可能性があるため、この動作に準拠していません。

ただし、強い参照に関する以下の点に注意してください。とにかくクリーンアップについて心配する必要があるかもしれません...?


3
通知ブロックに強い参照がない限り、オブザーバーを削除する必要があります。
TigerCoding 2016

オブザーバーをクリーンアップする必要がないための+1。知っておくべき重要!私はすべてのキャプチャ参照を弱くするので、これに対処する必要はありません。
n13 '10 / 10/26

2
ドキュメントによると、通知ブロックは常に強く参照されているようです。そのため、ブロックを使用して通知を処理している場合、deinit内でそれらの登録を解除する必要があります。
marsbear 2016年

22

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swiftは、不要になったインスタンスを自動的に割り当て解除して、リソースを解放します。自動参照カウントで説明されているように、Swiftは自動参照カウント(ARC)を通じてインスタンスのメモリ管理を処理します。通常、インスタンスの割り当てが解除されたときに手動でクリーンアップを実行する必要はありません。ただし、独自のリソースで作業している場合は、追加のクリーンアップを自分で実行する必要がある場合があります。たとえば、ファイルを開いてデータを書き込むカスタムクラスを作成する場合、クラスインスタンスの割り当てを解除する前にファイルを閉じる必要がある場合があります。

クラス定義は、クラスごとに最大1つの非初期化子を持つことができます。デイニシャライザはパラメータを取らず、括弧なしで記述されます。

deinit {
    // perform the deinitialization
}

2

割り当てを解除する前にオブザーバーを削除する必要があります。そうしないとクラッシュが発生します。それは使用して行うことができます

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}

-2

deinitから他のクラスのメソッドを呼び出すときは、おそらくクラッシュすることに注意してください


1
必ずしもそうではないはずです。参考文献から docsインスタンスはデイニシャライザが呼び出されるまで割り当て解除されないため、デイニシャライザは、呼び出されたインスタンスのすべてのプロパティにアクセスでき、それらのプロパティに基づいて動作を変更できます(必要なファイルの名前の検索など)閉じます)。
superjos 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.