Ще в кінці відповіді, але жоден з існуючих відповідей на це питання на самому ділі відповісти на питання OP, який є: чому, чорт візьми , ви б потрібно використовувати @objc
на private
член класу, якщо @objc
є для взаємодії з Objective-C, і член в питанні є приватним, тобто, навіть якщо у вашому проекті є код Objective-C, він все одно не зможе побачити учасника?
Причина в тому, що, оскільки багато фреймворків написані на Objective-C, іноді функції Objective-C потрібні для взаємодії з певними API.
Наприклад, припустимо, я хочу зареєструватися для отримання сповіщення за допомогою DistributedNotificationCenter
:
DistributedNotificationCenter.default.addObserver(self,
selector: #selector(somethingHappened(_:)),
name: someNotification,
object: nil)
Щоб це працювало, нам потрібно мати можливість отримати селектор somethingHappened
методу. Однак селектори - це концепція Objective-C, тому, якщо метод не видно Objective-C, він не має селектора. Отже, навіть якщо метод приватний і його не слід викликати довільним зовнішнім кодом, йому знадобиться, @objc
щоб DistributedNotification
код, який записаний в Objective-C, міг викликати його через його селектор.
Іншим поширеним випадком, коли @objc
це потрібно, є підтримка кодування значення-значення (KVC), особливо на macOS, де KVC та KVO використовуються для реалізації прив'язок какао. KVC, як і багато інших систем у какао, реалізований в Objective-C, що має наслідком вимагати, щоб властивості, сумісні з KVC, були піддані дії середовища Objective-C. Іноді має сенс, щоб властивості, сумісні з KVC, були приватними. Одним із прикладів є наявність властивості, яка впливає на інші властивості:
@objc private dynamic var originalProperty: String
@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
#keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
У цьому випадку наше фактичне збережене майно є приватним, але залежне властивість, яке ми надаємо зовнішньому коду, має надсилати свої сповіщення, коли приватне майно оновлюється. Позначивши приватну власність як @objc
, ми можемо легко це зробити, встановивши залежність KVC - інакше нам доведеться писати код, щоб вручну надсилати повідомлення в приватну власність willSet
та didSet
обробники. Крім того, статична властивість, яка інформує систему KVC, яка dependentProperty
залежить відoriginalProperty
має бути піддане дії Objective-C, щоб система KVC знаходила її та викликала, але це не стосується клієнтів нашого коду.
Крім того, контролер перегляду в програмі macOS, який оновлює елементи керування у своєму поданні, використовуючи Cocoa Bindings як деталь реалізації, може зробити деякі приватні властивості сумісними з KVC, щоб прив’язати ці елементи керування до них.
Отже, як бачите, бувають випадки, коли для взаємодії з фреймворками, можливо, метод або властивість повинні бути піддані дії Objective-C, без необхідності бути видимими для клієнтів вашого коду.