0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NSMapTableを活用する方法

Posted at

はじめに

NSMapTable は、NSDictionary に似た辞書型コレクションですが、キーと値の参照の持ち方を自由に設定できる という特徴があります。特に、キャッシュ用途に適しており、メモリ管理を最適化できます。

本記事では、

  • NSMapTable の基本
  • 強参照と弱参照の違い
  • キャッシュ管理への活用方法

を解説します。


NSMapTableとは?

NSMapTable は、NSDictionary に似た キーと値のペアを管理するコレクション ですが、以下の点が異なります。

NSMapTableの特徴

  1. キーと値のメモリ管理をカスタマイズ可能
    • Strong(強参照)Weak(弱参照) を自由に組み合わせられる
  2. 任意のオブジェクト型をキーにできる
    • NSDictionaryNSObject & NSCopying に準拠した型しかキーにできないが、NSMapTable は制限がない
  3. 自動メモリ管理(ARC)に適応
    • メモリに余裕がある間はオブジェクトを保持し、不要になると自動解放される

強参照と弱参照の違い

🛠 強参照(Strong Reference)とは?

  • あるオブジェクトが 他のオブジェクトを所有している状態
  • 参照がある限り、メモリから削除されない

例:強参照の問題(循環参照)

class Person {
    var pet: Pet?
}

class Pet {
    var owner: Person?
}

let person = Person()
let pet = Pet()

person.pet = pet
pet.owner = person // ⚠️ ここで循環参照が発生!
  • PersonPet を所有し、PetPerson を所有する
  • どちらも deinit されず、メモリリークが発生

解決策:片方を弱参照(weak)にする

class Pet {
    weak var owner: Person?
}

🌱 弱参照(Weak Reference)とは?

  • あるオブジェクトを参照していても、そのオブジェクトの生存に影響を与えない
  • 参照が nil になったら、メモリから自動的に解放される

例:弱参照を使ったメモリ管理

class ViewController: UIViewController {
    var cache = NSMapTable<NSString, AnyObject>.strongToWeakObjects()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let largeObject = NSObject()
        cache.setObject(largeObject, forKey: "key" as NSString)
        
        print(cache.object(forKey: "key" as NSString) != nil) // true
    }
}
  • largeObjectcache に格納されるが、他に参照がなければ deinit される

NSMapTableのメモリ管理オプション

オプション キー 使いどころ
strongToStrongObjects() 強参照 強参照 NSDictionary と同じ、データの保持が必要な場合
strongToWeakObjects() 強参照 弱参照 キャッシュ用途、不要になったら自動解放
weakToStrongObjects() 弱参照 強参照 キーが不要になったらエントリを削除
weakToWeakObjects() 弱参照 弱参照 どちらも不要になったら削除、最も軽量なキャッシュ

NSMapTableをキャッシュに活用する

NSMapTable はキャッシュ用途に使うことがありm。たとえば、documentCache を作成し、オブジェクトをメモリに保持しつつ、不要になったら自動解放できます。

📂 documentCache の例

private var documentCache = NSMapTable<NSString, AnyObject>.strongToWeakObjects()

🚀 使用例:一時的なオブジェクトキャッシュ

class Document {
    let name: String
    init(name: String) { self.name = name }
}

let cache = NSMapTable<NSString, AnyObject>.strongToWeakObjects()

// オブジェクトをキャッシュ
let doc = Document(name: "MyDoc")
cache.setObject(doc, forKey: "doc1" as NSString)

// キャッシュから取得
if let cachedDoc = cache.object(forKey: "doc1" as NSString) as? Document {
    print(cachedDoc.name) // "MyDoc"
}

// `doc` を解放するとキャッシュからも消える

ポイント

  • strongToWeakObjects() を使用することで、キャッシュに値を格納しても、他に参照がないと deinit される。
  • メモリが逼迫した際に 自動的に不要なデータが削除される ため、キャッシュとして便利。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?