Виправити це правильно - немає нічого про селектор, який ви можете змінити, щоб зробити метод, на який він посилається, піддається об’єкту-Objective-C.
Вся причина цього попередження в першу чергу є результатом SE-0160 . До Swift 4 internal
або вище об'єктів, що сумісні з Objective-C, NSObject
класів успадковування було зроблено висновок, @objc
а тому вони піддаються об'єкту-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, зважаючи на вищезазначені недоліки наявності членів без необхідності.
@objc
, що зараз необхідні для того, щоб виставити їх Obj-C, а тому використовувати разом із селекторами.