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

Я новичок в быстром, и вижу некоторые методы вроде:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

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

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

+71
источник поделиться
6 ответов

private означает, что он отображается только в 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

+52
источник

Еще один поздний ответ, но ни один из существующих ответов на этот вопрос действительно не отвечает на вопрос 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, у него нет селектора. Поэтому, даже если метод является закрытым и не должен вызываться произвольным внешним кодом, для кода DistributedNotification, который написан в Objective-C, для него может понадобиться @objc, чтобы иметь возможность называть его через его селектор.

Другим распространенным случаем, когда требуется @objc, является поддержка кодирования по ключевым словам (KVC), особенно на macOS, где KVC и KVO используются для реализации привязок Cocoa. KVC, как и многие другие системы в Cocoa, реализован в 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, иначе нам пришлось бы писать код, чтобы вручную отправлять уведомления в обработчиках private willSet и didSet. Кроме того, статическое свойство, информирующее систему KVC о том, что dependentProperty зависит от originalProperty, должно подвергаться Objective-C, чтобы система KVC находила ее и называла ее, но она не касалась клиентов нашего кода.

Кроме того, контроллер вида в приложении macOS, который обновляет элементы управления в своем представлении с помощью Cocoa Bindings в качестве детали реализации, может сделать определенные частные свойства KVC-совместимыми, чтобы связать эти элементы управления с ними.

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

+44
источник

@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.

+24
источник

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

@objc public class MyClass

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

+10
источник

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

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

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

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

+7
источник

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

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

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

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

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

    а. @objcMembers class - выставить все поля public fields и методами

    б. @objc class - выставить public init().
    @objc public поля и методы - чтобы выставить их выборочно

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

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

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

Подробнее здесь, здесь

+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос