Когда использовать @objc в быстром коде?

Я новичок в Swift, и я вижу некоторые методы, такие как:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

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

Тем не менее, это частная функция в swift, что делает @obj?

5 ответов

Решение

Частный означает, что это видно только в Swift. так что используйте @objc для отображения в Objective-C. Если у вас есть функция для выбора частного функции в swift, это необходимо.

Атрибут @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

Еще один поздний ответ, но ни один из существующих ответов на этот вопрос действительно не отвечает на вопрос ОП, а именно: зачем, черт возьми, вам понадобиться @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 необходимо поддерживать Key-Value Coding (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, который обновляет элементы управления в своем представлении, используя привязки Какао в качестве детали реализации, может сделать определенные частные свойства KVC-совместимыми, чтобы привязать эти элементы управления к ним.

Итак, как вы видите, бывают ситуации, когда метод или свойство, возможно, должны быть доступны Objective-C для взаимодействия с фреймворками, без необходимости быть видимыми для клиентов вашего кода.

@objc / dynamic

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

И используйте это, если хотите, чтобы к вашему свойству / методу обращался код или класс Objective-C.

В большинстве случаев это происходит, когда вы подклассифицируете класс Swift базового класса Objective-C.

Класс или протокол Swift должны быть помечены атрибутом @objc, чтобы быть доступными и используемыми в Objective-C. Этот атрибут сообщает компилятору, что этот фрагмент кода Swift доступен из Objective-C. Если ваш класс Swift является потомком класса Objective-C, компилятор автоматически добавит для вас атрибут @objc.

Вот яблочная документация, которая говорит о @objc,

Использование Swift из Objective-C

Совместимость языков

Обновленные ссылки:
Похоже, что ссылки были обновлены Apple.

@objc - это атрибут класса, поэтому вы используете

@objc public class MyClass

Он предоставляет методы классов классам Objective C, поэтому вы будете использовать его, только если ваш класс содержит публичные функции

Поздний ответ, но это @objc поведение немного меняется по сравнению со Swift 4 (который появился в Xcode 9, который был выпущен 10 дней назад).

В Swift 4 некоторые случаи вывода @objc удалены. Это просто означает, что в некоторых дополнительных случаях, когда до @objc заголовок был выведен компилятором Swift, он в Swift 4 не выведен.

Читайте больше в предложении Swift Evolution об этом изменении

Как уже упоминалось, в целом @objc состоит в том, чтобы представить определенные методы среде выполнения Objective C, которая является частью функциональной совместимости Swift с языком.

@objc представляет декларацию Objective-C runtime. Давайте посмотрим на#selectorфункция Swift для использования среды выполнения Objective-C. В этом случае вы можете определить свой Swift@objc private func [Больше]

Чтобы использовать функции Swift из Objective-C:

  1. Класс Swift должен быть расширен с NSObject
  2. Марка Свифта:

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

    б. @objc класс / перечисление / протокол (кроме структуры) [Именованный тип]

    • @objc class(необязательно) - выставить значение по умолчанию public init(). Или@objc(<custom_name>) чтобы настроить собственное имя для класса.
    • @objc конструкторы, поля и методы - чтобы выставлять их выборочно

Метод Swift будет доступен под следующим наименованием:

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

Например:

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

[@objc а также dynamic]

По умолчанию Swift генерирует код, который доступен только для других Swift код, но если вам нужно взаимодействовать с Objective-C время выполнения - все UIKit, например - вам нужно сказать Swift, что делать. Swift не делает свой код доступным для Objective-C по умолчанию, чтобы избежать увеличения размера кода.

Если вы просто хотите предоставить один метод или свойство, вы можете пометить этот метод, используя @objc приписывать. Однако, если вы хотите, чтобы все методы в классе подвергались воздействию Objective-C Вы можете использовать ярлык: @objcMembers ключевое слово.

Это полезно, например, когда вы работаете над Swift язык, и вы хотите использовать рамки из Objective-C код.

Чтобы использовать функции Swift из Objective-C:

  1. Класс Свифта должен быть расширен от NSObject
  2. Марк Свифт:

    а. @objcMembers класс - разоблачить все publicfields а также methods

    б. @objc класс - разоблачить public init(), Конкретный @objcpublicfields а также methods - выставлять их выборочно

    Метод Свифта будет доступен по следующим именам:

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

    Например: public func printHelloWorld(arg1: String, arg2:String) достигается через: [someObject printHelloWorldWithArg1: arg2:];

Узнайте больше здесь

Другие вопросы по тегам