Кандидат не "@objc", но протокол требует его
Я следил за этим tutorial, чтобы узнать, как быстро развивается приложение для приложений iOS. В разделе "Протокол" руководство разработало следующий протокол:
@objc protocol Speaker {
func Speak()
optional func TellJoke()
}
Он говорит Если вы хотите иметь протокол с дополнительными методами, вы должны префикс протокола тегом @objc (даже если ваш класс не взаимодействует с objective-C).
Затем он показывает образец для реализации протокола:
class Vicki: Speaker {
func Speak() {
println("Hello, I am Vicki!")
}
func TellJoke() {
println("Q: What did Sushi A say to Sushi B?")
}
}
Я попробовал вышеуказанный код на игровой площадке xcode, но я получил ошибку компилятора . Тип Vicki не соответствует протоколу Speaker ".
Xcode также выводит текст fix-it, в котором говорится, что "Кандидат не является" @objc ", но для этого требуется протокол.
Теперь я полностью запутался, в руководстве не упоминается эта ошибка вообще. Может ли кто-нибудь объяснить мне все это, чтобы я понял? Спасибо!
Ответы
Ответ 1
Из того, что я могу сказать, обозначение вашего протокола как @objc означает, что любые классы, реализующие его, также должны быть подвержены Objective-C. Это можно сделать либо путем создания Vicki подкласса NSObject:
class Vicki: NSObject, Speaker {
Или путем маркировки каждого реализованного метода как @objc:
class Vicki: Speaker {
@objc func Speak() {
print("Hello, I am Vicki!")
}
@objc func TellJoke() {
print("Q: What did Sushi A say to Sushi B?")
}
}
Обновление: от Apple документация Swift Language
Дополнительные требования к протоколу могут быть указаны только в том случае, если ваш протокол отмечен атрибутом @objc.
...
Обратите внимание, что протоколы @objc могут быть приняты только классами, а не по структурам или перечислениям. Если вы помечаете свой протокол как @objc в чтобы указать дополнительные требования, вы сможете подать заявку этот протокол для типов классов.
Ответ 2
Чтобы тип соответствовал протоколу, отмеченному @objc
, этот тип также должен быть помечен @objc
, или методы, используемые для удовлетворения протокола, должны быть.
Использование @objc
в объявлении указывает компилятору выставить его в среду выполнения Objective-C. Чтобы это было возможно, тип, объявленный @objc
, должен быть представлен в Objective-C.
Для классов это означает, что они должны унаследовать от NSObject. Для методов это означает, что они поддерживаются динамической передачей сообщений Objective-C.
Ответ 3
Похоже, нам нужен только префикс метода протокола с @objc
в закрытом классе.
private class A: NSObject, SomeObjcProtocol {
@objc func someProtocolMethod() {}
}
Предупреждение вряд ли будет повышаться для не-частного класса.
class A: NSObject, SomeObjcProtocol {
func someProtocolMethod() {}
}
Оба прекрасны.
Ответ 4
Добавьте расширение для протокола, возвращающего пустые функции и значения по умолчанию. Любой класс, который соответствует протоколу и хочет переопределить любые функции func или var, может, возможно, сделать это.
public protocol Speaker {
func Speak()
func TellJoke()
}
extension Speaker {
func Speak() {}
func TellJoke() { print("What did the Teabag say to the Octopus?"}
}
Бонусы: вы не наследуете весь багаж obj-c.