Ответ 1
Исправить - это правильно - ничего о селекторе, который вы можете изменить, чтобы сделать метод, на который он ссылается, подвергается Objective-C.
Вся причина этого предупреждения в первую очередь - результат SE-0160. До Swift 4, internal
или выше Objective-C совместимые члены классов наследования NSObject
были определены как @objc
и поэтому подвергались воздействию Objective-C, поэтому позволяли им вызываться с использованием селекторов (как Obj-C время выполнения требуется для поиска реализации метода для данного селектора).
Однако в Swift 4 это уже не так. В настоящее время допускаются только очень конкретные объявления: @objc
, например, переопределения методов @objc
, реализации требований протокола @objc
и деклараций с атрибутами, которые подразумевают @objc
, например @IBOutlet
.
Мотивация этого, как указано в в вышеупомянутом связанном предложении, во-первых, заключается в предотвращении перегрузки методов в NSObject
наследовании классов от столкновений с друг друга из-за наличия идентичных селекторов. Во-вторых, это помогает уменьшить размер двоичного файла, не создавая трюков для членов, которые не должны подвергаться Obj-C, и, в-третьих, улучшает скорость динамической компоновки.
Если вы хотите выставить элемент в Obj-C, вам нужно пометить его как @objc
, например:
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(foo), for: .touchUpInside)
}
@objc func foo() {
// ...
}
}
(мигратор должен сделать это автоматически для вас с помощью селекторов при запуске с опцией "минимизировать вывод" )
Чтобы выставить группу членов в Obj-C, вы можете использовать @objc extension
:
@objc extension ViewController {
// both exposed to Obj-C
func foo() {}
func bar() {}
}
Это выведет все члены, определенные в нем, в Obj-C и даст ошибку для любых членов, которые не могут быть подвергнуты Obj-C (если явно не указано как @nonobjc
).
Если у вас есть класс, в котором вам нужно, чтобы все члены, совместимые с Obj-C, подвергались воздействию Obj-C, вы можете пометить класс как @objcMembers
:
@objcMembers
class ViewController: UIViewController {
// ...
}
Теперь все члены, которые могут быть определены как @objc
, будут. Тем не менее, я бы не советовал делать это, если вам действительно не нужны все участники, подвергшиеся воздействию Obj-C, учитывая вышеупомянутые недостатки, связанные с тем, что члены были необоснованными.