0Pricing
Swift Academy · レッスン

オブザーバーの安全な削除

古いオブザーバーによるリークやクラッシュを防ぎます。

「オブザーバーの安全な削除」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

オブザーバーを安全に削除する

不要になったオブザーバーは削除する必要があります。残ったオブザーバーが所有者の破棄後に実行されると、バグの原因になります。古いAPIではクラッシュにつながることもあります。

削除が重要な理由

セレクタによるオブザーバーは、解放済みのオブジェクトにメッセージを送らないよう、従来はdeinitで削除する必要がありました。

import Foundation

class Watcher: NSObject {
    override init() { super.init() }
    deinit { NotificationCenter.default.removeObserver(self) }
}
print("Removes itself on deinit")

removeObserver(self)

removeObserver(self)を呼び出すと、そのオブジェクトが登録したすべての監視を1回で解除できます。

import Foundation

class VM: NSObject {
    func stop() { NotificationCenter.default.removeObserver(self) }
}
VM().stop()
print("Removed all observations for self")

特定の名前を削除する

名前とオブジェクトを渡せば、1つの監視だけを削除し、ほかの監視はそのまま残せます。

import Foundation

let center = NotificationCenter.default
let obj = NSObject()
let name = Notification.Name("ping")
center.removeObserver(obj, name: name, object: nil)
print("Removed a specific observation")

トークンによるオブザーバー

クロージャベースのaddObserverは、不透明なトークンを返します。そのトークンを保持し、トークンを使ってオブザーバーを削除します。

import Foundation

let center = NotificationCenter.default
let name = Notification.Name("ping")
let token = center.addObserver(forName: name, object: nil, queue: nil) { _ in }
center.removeObserver(token)
print("Removed via token")

トークンを保存する

監視を続けたい期間だけトークンが存続するよう、プロパティに保存します。監視が不要になったら削除します。

import Foundation

class Model {
    var token: NSObjectProtocol?
    func start() {
        token = NotificationCenter.default.addObserver(
            forName: Notification.Name("x"), object: nil, queue: nil) { _ in }
    }
    func stop() {
        if let t = token { NotificationCenter.default.removeObserver(t) }
    }
}
let m = Model(); m.start(); m.stop()
print("Lifecycle managed")

deinitによる自動クリーンアップ

deinitでトークンを削除すると、所有者が解放されたときに監視も終了します。

import Foundation

class Owner {
    var token: NSObjectProtocol?
    deinit { if let t = token { NotificationCenter.default.removeObserver(t) } }
}
print("Token removed on deinit")

最新のランタイムに関する注意

最近のランタイムでは、ブロックAPIで追加したオブザーバーはトークンが解放されると自動的に削除されます。ただし、明示的に削除するほうが安全で分かりやすい方法です。

import Foundation

// Holding the token in a property controls its lifetime.
class C { var token: NSObjectProtocol? }
print("Token lifetime equals observation lifetime")

強い参照サイクルを避ける

クロージャオブザーバーがselfを強くキャプチャする場合は、解放を妨げる強い参照サイクルを避けるために[weak self]を使います。

import Foundation

class VM {
    var token: NSObjectProtocol?
    func start() {
        token = NotificationCenter.default.addObserver(
            forName: Notification.Name("x"), object: nil, queue: nil) { [weak self] _ in
            self?.handle()
        }
    }
    func handle() { print("handled") }
}
VM().start()

二重削除は安全

すでに削除されたオブザーバーを再度削除しても問題ありません。そのため、防御的なクリーンアップでクラッシュすることはありません。

import Foundation

let center = NotificationCenter.default
let obj = NSObject()
center.removeObserver(obj)
center.removeObserver(obj) // no harm
print("Safe to remove twice")

ベストプラクティスのまとめ

トークンベースのクロージャを優先し、トークンを保存してdeinitで削除し、selfは弱くキャプチャします。これにより、監視のライフタイムを正しく管理できます。

import Foundation

class Best {
    var token: NSObjectProtocol?
    deinit { token.map { NotificationCenter.default.removeObserver($0) } }
}
print("Followed best practices")

理解度チェック

addObserver(forName:...)で追加したクロージャベースのオブザーバーは、どのように削除しますか?

まとめ

不要になったオブザーバーは必ず削除します。セレクタによるオブザーバーにはremoveObserver(self)を使い、クロージャによるオブザーバーには返されたトークンを使います。トークンを保存し、deinitでクリーンアップし、selfは弱くキャプチャします。次は、オブザーバーパターンと代替手段を比較します。

よくある質問

「オブザーバーの安全な削除」レッスンは無料ですか?

はい。「オブザーバーの安全な削除」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「オブザーバーの安全な削除」で何を学びますか?

古いオブザーバーによるリークやクラッシュを防ぎます。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「オブザーバーの安全な削除」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 通知の投稿と監視
  2. NotificationのuserInfoペイロード
  3. オブザーバーの安全な削除
  4. Observerパターンの代替手段
← Swift Academyに戻る