Протокол Swift @objc — различать необязательные методы с похожей сигнатурой

Допустим, у нас есть протокол в Swift:

@objc protocol FancyViewDelegate {
  optional func fancyView(view: FancyView, didSelectSegmentAtIndex index: Int)
  optional func fancyView(view: FancyView, shouldHighlightSegmentAtIndex index: Int) -> Bool
}

Обратите внимание, что оба метода являются необязательными и имеют одинаковую сигнатуру префикса.

Теперь наш класс FancyView выглядит так:

class FancyView: UIView {
  var delegate: FancyViewDelegate?

  private func somethingHappened() {
    guard let delegateImpl = delegate?.fancyView else {
      return
    }

    let idx = doALotOfWorkToFindTheIndex()

    delegateImpl(self, idx)
  }
}

Компилятор бросается нам в глаза:

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

Мы могли бы изменить somethingHappened() на это:

private func somethingHappened() {
  let idx = doALotOfWorkToFindTheIndex()

  delegate?.fancyView?(self, didSelectSegmentAtIndex: idx)
}

Однако, как вы можете видеть, мы рискуем сделать много работы только для того, чтобы потом выбросить индекс, потому что делегат не реализует необязательный метод.

Вопрос в том, как нам if let или guard let связать реализацию двух необязательных методов с похожей сигнатурой префикса.


person CodingMeSwiftly    schedule 04.12.2015    source источник
comment
Я бы по-прежнему использовал responsesToSelector и вызывал соответствующий метод, если он поддерживается.   -  person Shripada    schedule 04.12.2015


Ответы (1)


Во-первых, ваш целевой протокол C должен подтвердить NSObjectProtocol, чтобы убедиться, что мы можем самостоятельно проверить, поддерживает ли он данный метод.

Затем, когда мы хотим вызвать определенный метод, проверьте, поддерживается ли этот метод соответствующим объектом, и если да, то выполните необходимые вычисления, необходимые для вызова этого метода. Я попробовал этот код, например,

  @objc protocol FancyViewDelegate : NSObjectProtocol {
      optional func fancyView(view: UIView, didSelectSegmentAtIndex index: Int)
      optional func fancyView(view: UIView, shouldHighlightSegmentAtIndex index: Int) -> Bool
    }


    class FancyView: UIView {
      var delegate: FancyViewDelegate?

      private func somethingHappened() {
        if delegate?.respondsToSelector("fancyView:didSelectSegmentAtIndex") == true {
          let idx :Int  = 0 //Compute the index here
          delegate?.fancyView!(self, didSelectSegmentAtIndex: idx)
        }
      }
    }
person Shripada    schedule 04.12.2015