Подтвердить что ты не робот

Кандидат не "@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 ", но для этого требуется протокол.

Теперь я полностью запутался, в руководстве не упоминается эта ошибка вообще. Может ли кто-нибудь объяснить мне все это, чтобы я понял? Спасибо!

4b9b3361

Ответ 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.