Poprawka jest poprawna - nie ma nic w selektorze, który możesz zmienić, aby metoda, do której się odnosi, była ujawniona w celu-C.
Cały powód tego ostrzeżenia w pierwszej kolejności wynika z SE-0160 . Przed Swift 4 internal
lub nowszym NSObject
składowe klas dziedziczących zgodne z Objective-C były wywnioskowane, @objc
a tym samym narażone na Objective-C, dzięki czemu można je wywoływać za pomocą selektorów (ponieważ środowisko uruchomieniowe Obj-C jest wymagane do wyszukania metody implementacja dla danego selektora).
Jednak w Swift 4 już tak nie jest. Obecnie tylko bardzo specyficzne deklaracje są wywnioskowane jako @objc
na przykład przesłonięcia @objc
metod, implementacje @objc
wymagań protokołu i deklaracje z atrybutami, które implikują @objc
, takie jak @IBOutlet
.
Motywacją do tego, jak opisano szczegółowo w powyższej połączonej propozycji , jest po pierwsze zapobieganie NSObject
kolizji przeciążeń metod w dziedziczeniu klas ze względu na posiadanie identycznych selektorów. Po drugie, pomaga zmniejszyć rozmiar binarny, ponieważ nie musi generować zwrotów dla członków, którzy nie muszą być narażeni na Obj-C, a po trzecie poprawia prędkość dynamicznego łączenia.
Jeśli chcesz wystawić członka na Obj-C, musisz oznaczyć go jako @objc
na przykład:
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(foo), for: .touchUpInside)
}
@objc func foo() {
}
}
(migrator powinien to zrobić automatycznie z selektorami, gdy jest uruchomiony z wybraną opcją „minimalizuj wnioskowanie”)
Aby wystawić grupę członków na Obj-C, możesz użyć @objc extension
:
@objc extension ViewController {
func foo() {}
func bar() {}
}
Spowoduje to ujawnienie wszystkich zdefiniowanych w nim elementów członkowskich Obj-C i spowoduje wyświetlenie błędu w przypadku wszystkich elementów członkowskich, których nie można ujawnić Obj-C (chyba że wyraźnie oznaczono jako @nonobjc
).
Jeśli masz klasę, w której chcesz, aby wszyscy członkowie zgodni z Obj-C byli narażeni na działanie Obj-C, możesz oznaczyć klasę jako @objcMembers
:
@objcMembers
class ViewController: UIViewController {
}
Teraz wszyscy członkowie, o których można wywnioskować, @objc
że są. Jednak nie radziłbym tego robić, chyba że naprawdę potrzebujesz wszystkich członków narażonych na Obj-C, biorąc pod uwagę wyżej wymienione wady niepotrzebnego ujawniania członków.
@objc
jest już konieczne, aby wystawiać na działanie obj-C, a zatem użycia z przełączników.