Коли використовувати @objc у Swift?


87

У Swift я бачу такі методи, як:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

Мені було цікаво, коли використовувати @objc? Я прочитав деякі документи, але вони кажуть, що коли ви хочете, щоб він викликався в Objective-C, вам слід додати прапор @objc

Однак це приватна функція в Swift, що робить @obj?


1
приємне питання !!!
Ерхан

Відповіді:


67

private означає, що це видно лише в Swift. тому використовуйте @objc для видимості в Objective-C. Якщо у вас є функція швидкого вибору приватної функції, це потрібно.

Атрибут @objc робить ваш Swift API доступним у Objective-C та середовищі виконання Objective-C.

Див .: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html


1
отже @objc private func doubleTapGestureRecognized, який сенс мати і @objc, і приватний? Ви хочете сказати, що класи Objective-C можуть перезаписати doubleTapGestureRecognized?
Wingzero

1
Я здогадуюсь, тому що у obj-c ви можете переписати будь-який метод у будь-якому випадку.
Strangetimes

2
Не впевнений, наскільки ця відповідь правильна, і відповідає на його запитання. Надані тут відповіді вже є у самому його запитанні ", але вони кажуть, що коли ви хочете, щоб він викликався в Objective-C, вам слід додати прапор \ @objc", його основний Питання: "Це швидка приватна функція, що робить \ @obj?"
KBJ

3
Посилання розриваються. Особливо в документації Apple. Будь ласка, розгляньте можливість вилучення ключових елементів із документації тут.
levigroker

55

Ще в кінці відповіді, але жоден з існуючих відповідей на це питання на самому ділі відповісти на питання 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, без необхідності бути видимими для клієнтів вашого коду.


25

@objc / динамічний

Це для сумісності: як тільки ви імпортуєте файл / код Swift до проекту на основі Objective-C.

І використовуйте це, якщо хочете, щоб доступ до вашого властивості / методу здійснювався за допомогою коду або класу Objective-C.

Найчастіше це відбувається, коли ви підкласуєте клас Swift базового класу Objective-C.

Клас або протокол Swift повинні бути позначені атрибутом @objc, щоб бути доступним і придатним для використання в Objective-C. Цей атрибут повідомляє компілятору, що цей шматок коду Swift можна отримати з Objective-C. Якщо ваш клас Swift є нащадком класу Objective-C, компілятор автоматично додає для вас атрибут @objc.

Ось документація щодо яблук, яка говорить про @objc.

Використання Swift з Objective-C

Сумісність мовної сумісності

Посилання оновлено:
схоже, посилання оновив Apple.


11

@objc - це атрибут класу, тому ви використовуєте

@objc public class MyClass

Він виставляє методи класу до класів Objective C, тому ви будете використовувати їх, лише якщо ваш клас містить загальнодоступні функції


7

Пізня відповідь, але це @objc поведінка дещо змінюється станом на Swift 4 (який вийшов у Xcode 9, який, як правило, вийшов 10 днів тому).

У Swift 4 деякі випадки умовиводу @objcвидалено. Це просто означає в деяких додаткових випадках, коли до@objc заголовка було виведено компілятором Swift, це в Swift 4 не виведено.

Прочитайте більше про пропозицію Swift evolution про цю зміну

Як вже було згадано, загалом @objcце піддавати певні методи середовищу виконання Objective-C, що є частиною взаємодії Свіфта з мовою.


1
отже, це повинно бути причиною того, що після оновлення до Swift 4 деякі змінні недоступні з ObjC, чи не так? З Swift 3.X не було потреби додавати@objc
rgkobashi

о гаразд, це завжди добре ще раз перевірити когось іншого, дякую!
rgkobashi

1

@objcвиставляє декларацію Objective-C runtime. Давайте розглянемо #selectorособливості Swift для використання середовища виконання Objective-C. У цьому випадку ви можете визначити свій Swift @objc private func[Докладніше]

Щоб використовувати функції Swift з Objective-C:

  1. Клас Свіфта слід продовжити з NSObject
  2. Марк Свіфт:

    a. тільки @objcMembers клас - виставити всі public конструктори , поля та методи . Також він застосовується для підкласів

    b. @objc клас / перелік / протокол (крім структури ) [Іменований тип]

    • @objc клас (за бажанням) - щоб виставити за замовчуванням public init() . Або @objc(<custom_name>)встановити власну назву для класу.
    • @objc конструктори , поля та методи - вибирати їх вибірково

Метод Свіфта буде доступний при наступному іменуванні:

<swiftName>With<firstArgument>:<secondArgument>:

Наприклад:

public func printHelloWorld(arg1: String, arg2:String)
//is reached through: 
[someObject printHelloWorldWithArg1: arg2:];

[ @objcта dynamic]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.