Протокол Swift вложен в класс

Я хотел бы вложить протокол в моем классе для реализации шаблона делегата следующим образом:

class MyViewController : UIViewController {

    protocol Delegate {
        func eventHappened()
    }

    var delegate:MyViewController.Delegate?

    private func myFunc() {
        delegate?.eventHappened()
    }
}

Но компилятор этого не допустит:

Протокол "Делегат" не может быть вложен в другое объявление

Я легко могу заставить его работать, объявив MyViewControllerDelegate вне области видимости класса.
У меня вопрос, почему такое ограничение?

Ответ 1

в соответствии с быстрой документацией

Swift позволяет вам определять вложенные типы, посредством которых вы устанавливаете поддерживающие перечисления, классы и структуры в определении типа, который они поддерживают.

Данные протоколы не входят в этот список, но не отображаются в настоящее время. Возможно, в какой-то момент они добавят эту функцию (вскоре объявили, что Swift прошло менее 2 лет). Любая идея о том, почему они не будут или не были бы, было бы спекуляцией с моей стороны.

Ответ 2

это моя работа вокруг:

  protocol MyViewControllerDelegate : class {
     func eventHappened()
  }
  class MyViewController : UIViewController {
     typealias Delegate = MyViewControllerDelegate
     weak var delegate: Delegate?

     private func myFunc() {
         delegate?.eventHappened()
     }

  }

Ответ 3

Отдельная проблема с вашим классом заключается в том, что delegate не имеет конкретного типа. Вы можете уйти от объявления MyViewController.Delegate?, потому что это необязательный тип и может быть .None. Но это просто делает ваш закрытый myFunc мертвый код. Только перечисления, классы и структуры могут соответствовать протоколу. Какой из этих трех типов delegate?

Тем не менее, это не причина вашей проблемы. Когда я делаю реальный тип для delegate и согласую его с протоколом delegate, я все равно получаю ту же ошибку.

class MyViewController: UIViewController {

  protocol Delegate {
    func eventHappened()
  }

  class Classy: Delegate {
    func eventHappened() {
      print("eventHappened")
    }
  }

  var delegate: Classy? = Classy()

  func myFunc() {
    delegate?.eventHappened()
  }
}

введите описание изображения здесь

В качестве эзотерического упражнения это может быть интересно в том, чтобы подтолкнуть границы того, что может сделать класс, но никто не должен пытаться объявить протокол внутри класса. Протоколы касаются составов и коллекций типов. Нет сценария повторного использования кода, если вы ограничены тем, что находитесь в одном и том же внешнем классе.