Ответ
Комбинация @objc final создаёт гибридный механизм диспетчеризации, оптимизированный для взаимодействия Swift и Objective-C.
Разбор по модификаторам:
-
final— запрещает переопределение метода в подклассах. Для компилятора Swift это сигнал использовать статическую (прямую) диспетчеризацию. Вызов метода происходит напрямую по известному адресу в памяти, без поиска в таблице виртуальных функций (vtable), что даёт прирост производительности. -
@objc— делает метод видимым для Objective-C runtime. Для этого он добавляется в Objective-C runtime таблицу диспетчеризации, что подразумевает возможность динамической диспетчеризации при вызове из Objective-C кода или через механизмы вроде#selector.
Итоговое поведение:
- В Swift-коде: Вызов метода будет происходить через статическую диспетчеризацию (благодаря
final), что максимально эффективно. - В Objective-C коде или через селекторы: Вызов будет происходить через динамическую диспетчеризацию Objective-C runtime (благодаря
@objc).
Пример:
@objc final class NetworkService: NSObject {
@objc final func sendRequest() {
// Реализация метода
}
}
let service = NetworkService()
// Вызов из Swift — СТАТИЧЕСКАЯ диспетчеризация (быстро)
service.sendRequest()
// Вызов через селектор — ДИНАМИЧЕСКАЯ диспетчеризация через Objective-C
let selector = #selector(NetworkService.sendRequest)
service.perform(selector)
Когда это полезно: При создании Swift-классов, которые должны быть:
- Эффективными внутри Swift-кода (статическая диспетчеризация).
- Доступными для KVO, таргет-экшнов (
#selector), или вызовов из legacy Objective-C кода (динамическая диспетчеризация).