Я погуглил, но не смог выяснить, что такое быстрый эквивалент respondsToSelector:
.
Это единственное, что я могу найти ( альтернатива Swift для responsedsToSelector:), но это не слишком уместно в моем случае, так как он проверяет наличие делегата, у меня нет делегата, я просто хочу проверить, существует ли новый API или нет при запуске на устройстве и, если нет, вернуться к предыдущей версии API.
objective-c
swift
selector
Gruntcakes
источник
источник
NSClassFromString
иrespondsToSelector
среди других механизмов для проверки недавно реализованной функциональности, я должен верить, что механизмы либо уже существуют, либо будут там до выпуска. Попробуйте посмотретьAdvanced Interop...
видео с WWDC.if #available(...)
в Swift 2.x, чтобы избежать использованияrespondsToSelector
в первую очередь. Но ты знал это. ( apple.co/1SNGtMQ )Ответы:
Как уже упоминалось, в Swift большую часть времени вы можете достичь того, что вам нужно, с помощью
?
дополнительного оператора распаковки . Это позволяет вам вызывать метод объекта тогда и только тогда, когда объект существует (не существуетnil
) и метод реализован.В случае, когда вам все еще нужно
respondsToSelector:
, это все еще там как частьNSObject
протокола.Если вы вызываете
respondsToSelector:
тип Obj-C в Swift, то он работает так же, как и ожидалось. Если вы используете его в своем собственном классе Swift, вам необходимо убедиться, что ваш класс является производным от негоNSObject
.Вот пример класса Swift, который вы можете проверить, реагирует ли он на селектор:
Важно, чтобы вы не пропускали имена параметров. В этом примере
Selector("sleep::")
это не то же самое, чтоSelector("sleep:minutes:")
.источник
let x =
часть. По сути,if let x = y
структура заключается в развертывании необязательных значений (аналогично!
). Поскольку вы получаетеBool
ответrespondsToSelector
, компилятор жалуется, что результат не является необязательным типом (Bool?
).var
с объявленным? Они по-прежнему реагируют одинаково? В Objective-C я мог бы сделатьif ( [obj respondsToSelector:@selector(setSomeVar:)] ) { ... }
дляsomeVar
собственности. Работает ли так же сvar
s в Swift?Там нет реальной замены Swift.
Вы можете проверить следующим образом:
Это вызывает метод,
someMethod
только если он определен для объекта,someObject
но вы можете использовать его только для@objc
протоколов, которые объявили метод какoptional
.Swift по своей природе является безопасным языком, поэтому каждый раз, когда вы вызываете метод, Swift должен знать, что этот метод существует. Проверка во время выполнения невозможна. Вы не можете просто вызывать случайные методы для случайных объектов.
Даже в Obj-C вы должны избегать подобных вещей, когда это возможно, потому что это не очень хорошо работает с ARC (ARC затем вызывает предупреждения
performSelector:
).Однако при проверке доступных API вы все равно можете использовать
respondsToSelector:
, даже если Swift, если вы имеете дело сNSObject
экземплярами:источник
respondsToSelector:
как рекомендация Apple явно, что вы должны это делать. Смотрите здесьrespondsToSelector:
это действительно полезно иметь. Но если вы перейдете по ссылке на Swift, они говорят об использовании подклассов для разных версий системы.if #available(iOS 10) {
а затем вызываем метод напрямую.Обновление 20 марта 2017 года для синтаксиса Swift 3:
Если вам все равно, существует ли необязательный метод, просто вызовите
delegate?.optionalMethod?()
В противном случае, использование
guard
, вероятно, лучший подход:Оригинальный ответ:
Вы можете использовать подход «если позволите», чтобы проверить дополнительный протокол, подобный этому:
источник
let theMethod = delegate.userNotificationCenter(_:willPresent:withCompletionHandler:)
Кажется, вам нужно определить свой протокол как подпроток NSObjectProtocol ... тогда вы получите метод responsedsToSelector
обратите внимание, что только указание @objc было недостаточно. Вы также должны быть осторожны, что фактический делегат является подклассом NSObject - чего в Swift может и не быть.
источник
Если метод, который вы тестируете, определен как необязательный метод в протоколе @objc (который звучит как ваш случай), то используйте дополнительный шаблон цепочки как:
Когда метод объявлен как возвращаемый
Void
, просто используйте:Видеть:
источник
if object.method?(args) { ... }
- вызов метода, если он существует, вернет,Void
которого нетnil
object
имеет типAnyObject
, вы можете протестировать любой метод @objc.Функции являются первоклассными типами в Swift, поэтому вы можете проверить, была ли реализована дополнительная функция, определенная в протоколе, сравнив ее с nil:
источник
Для swift3
Если вы просто хотите вызвать метод, запустите код ниже.
self.delegate?.method?()
источник
В Swift 2 Apple представила новую функцию под названием
API availability checking
, которая может заменитьrespondsToSelector:
метод. Следующее сравнение фрагментов кода скопировано из сеанса 106 WWDC2015 « Что нового в Swift», которое, как я думал, может вам помочь, пожалуйста, проверьте его, если вам нужно узнать больше.источник
respondsToSelector
подхода в Swift. Это также потому, что проверка селектора не была лучшим решением этой проблемы (проверка доступности).Для Swift 3.0
источник
В настоящее время (Swift 2.1) вы можете проверить это тремя способами:
Используя '?' ответил @Sulthan
И с помощью
as?
оператора:В основном это зависит от того, чего вы пытаетесь достичь:
источник
Я просто сам реализую это в проекте, см. Код ниже. Как упоминает @Christopher Pickslay, важно помнить, что функции являются гражданами первого класса и поэтому могут рассматриваться как необязательные переменные.
источник
другой возможный синтаксис по быстрому ..
источник
Когда я начал обновлять свой старый проект до Swift 3.2, мне просто нужно было изменить метод с
чтобы:
источник
Я использую
guard let else
, так что это может сделать некоторые вещи по умолчанию, если функция делегата не реализована.источник
Свифт 3:
протокол
объект
источник
Эквивалент? оператор:
важный метод будет вызываться только в том случае, если myQuestionableObject существует и реализует его.
источник
?
послеimportantMethod