← Назад к вопросам

Что такое NSHashTable?

2.0 Middle🔥 71 комментариев
#Коллекции и структуры данных#Управление памятью

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое NSHashTable в iOS/macOS разработке?

NSHashTable — это изменяемая коллекция, аналогичная NSSet, но предоставляющая гораздо более гибкие возможности по управлению памятью и сравнения объектов. В то время как стандартный NSSet и его изменяемая версия NSMutableSet хранят объекты как "сильные" ссылки (strong) и требуют, чтобы объекты соответствовали протоколу NSCopying, NSHashTable лишён этих ограничений. Это делает его мощным инструментом для специфических сценариев, особенно связанных с жизненным циклом объектов.

Ключевые особенности и отличия от NSSet

1. Варианты хранения ссылок (Memory Policy)

Самое важное свойство NSHashTable — возможность выбора типа ссылки на хранимые объекты через перечисление NSPointerFunctionsOptions. Основные варианты:

  • .strongMemory: Аналогично NSSet — сильные ссылки, объекты удерживаются коллекцией.
  • .weakMemory: Слабые ссылки — коллекция не препятствует уничтожению объекта. Автоматически удаляет nil (обнулённые ссылки), что идеально для кешей или наблюдателей без создания retain cycle.
  • .copyIn: При добавлении объект копируется (должен соответствовать NSCopying).

Инициализация с определённой политикой памяти:

// Хэш-таблица со слабыми ссылками (чаще всего используется)
let weakTable = NSHashTable<AnyObject>(options: .weakMemory)

// Хэш-таблица с сильными ссылками (как NSSet, но без требования NSCopying)
let strongTable = NSHashTable<AnyObject>(options: .strongMemory)

2. Отсутствие требования к NSCopying

В NSHashTable можно добавлять любые объекты, не заботясь о протоколе NSCopying. Это полезно для объектов, которые не должны или не могут копироваться.

class MyClass {
    let id: String
    init(id: String) { self.id = id }
}

let myObject = MyClass(id: "unique")
let hashTable = NSHashTable<AnyObject>()
hashTable.add(myObject) // Ошибки не будет, даже если MyClass не соответствует NSCopying

3. Гибкость сравнения и хеширования

NSHashTable позволяет настраивать функции сравнения и хеширования объектов (через NSPointerFunctions), но на практике это требуется редко.

Основные методы работы

let table = NSHashTable<AnyObject>(options: .weakMemory)

// Добавление объектов
let obj1 = NSObject()
let obj2 = NSObject()
table.add(obj1)
table.add(obj2)

// Проверка наличия объекта
if table.contains(obj1) {
    print("Объект находится в таблице")
}

// Удаление объекта
table.remove(obj1)

// Получение всех объектов
let allObjects = table.allObjects // Возвращает массив [AnyObject]

// Итерация по объектам
for object in table.allObjects {
    print(object)
}

Типичные сценарии использования

1. Избегание retain cycles через слабые ссылки

Наиболее частый случай — хранение массива делегатов или наблюдателей.

class EventManager {
    private weak var delegates = NSHashTable<AnyObject>(options: .weakMemory)
    
    func addDelegate(_ delegate: EventDelegate) {
        delegates.add(delegate)
    }
    
    func notifyDelegates() {
        for delegate in delegates.allObjects {
            (delegate as! EventDelegate).eventDidOccur()
        }
    }
}

protocol EventDelegate: AnyObject {
    func eventDidOccur()
}

Здесь делегаты не удерживаются EventManager, и они автоматически удаляются из коллекции при деаллокации.

2. Хранение объектов без возможности копирования

Когда нужно работать с объектами, которые не поддерживают NSCopying.

3. Создание пользовательских кешей

Слабые таблицы могут служить основой для кешей, которые автоматически очищаются при нехватке памяти (объекты удаляются сборщиком мусора).

4. Множества с нестандартным поведением

Когда требуется особенная семантика сравнения или хранения объектов.

NSHashTable vs NSSet: сводная таблица

КритерийNSHashTableNSSet/NSMutableSet
Тип ссылокНастраиваемый (strong, weak, copy)Только strong
NSCopyingНе требуетсяОбязательно для добавления
ПроизводительностьМожет быть немного медленнееОптимизирована для стандартных задач
Порядок элементовНе гарантированНе гарантирован
Удаление nilАвтоматически при weakMemoryНе применимо

Заключение

NSHashTable — это специализированный инструмент для работы с коллекциями в ситуациях, где стандартные NSSet или NSArray недостаточны. Его главная сила — в гибкой политике управления памятью, особенно при использовании слабых ссылок (.weakMemory), что делает его незаменимым для реализации паттернов с наблюдателями, делегатами и кешами без создания циклов удержания. Однако для обычных задач хранения объектов с сильными ссылками NSSet остаётся более простым и производительным выбором.

Что такое NSHashTable? | PrepBro