Виправити це правильно - немає нічого про селектор, який ви можете змінити, щоб зробити метод, на який він посилається, піддається об’єкту-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, а тому використовувати разом із селекторами.