Невозможно получить событие с помощью настраиваемого DelegateProxy и протокола

Я пытаюсь перенести делегат DifficultyViewDelegate в наблюдаемый. Это мой DifficultyViewDelegate:

@objc protocol DifficultyViewDelegate: class {
  func levelDidIncrease()
  func levelDidDecrease()
}

И мой DifficultyView:

  weak var delegate: DifficultyViewDelegate?

  @IBAction func decreaseLevel(_ sender: Any) {
    delegate?.levelDidDecrease()
  }

  @IBAction func increaseLevel(_ sender: Any) {
    delegate?.levelDidIncrease()
  }

А это мой RxDifficultyViewDelegateProxy

class RxDifficultyViewDelegateProxy: DelegateProxy, DelegateProxyType {
  static func currentDelegateFor(_ object: AnyObject) -> AnyObject? {
    let difficultyView: DifficultyView = object as! DifficultyView
    return difficultyView.delegate
  }

  static func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) {
    let difficultyView: DifficultyView = object as! DifficultyView
    difficultyView.delegate = delegate as? DifficultyViewDelegate
  }
}

Я также добавил расширение в свой DifficultyView:

extension DifficultyView {
  public var rx_delegate: RxDifficultyViewDelegateProxy {
    return  RxDifficultyViewDelegateProxy.proxyForObject(RxDifficultyViewDelegateProxy.self)
  }

  public var rx_levelDidIncrease: Observable<Void> {
    return rx_delegate.methodInvoked(#selector(DifficultyViewDelegate.levelDidIncrease)).map { _ in return }
  }
}

Но кажется, что когда я это сделаю:

difficultyView.rx_levelDidIncrease.asObservable().subscribe(onNext: {
  print("did increase")
}).addDisposableTo(disposeBag)

Это никогда не называлось. У кого-нибудь есть указатели?


person Aymen Rebouh    schedule 21.01.2017    source источник


Ответы (1)


Попробуйте использовать PublishSubject:

DifficultyView:

class DifficultyView: UIView {
    var levelDidIncrease = PublishSubject<Void>()
    var levelDidDecrease = PublishSubject<Void>()

    @IBAction func decreaseLevel(_ sender: Any) {
        levelDidDecrease.onNext()
    }

    @IBAction func increaseLevel(_ sender: Any) {
        levelDidIncrease.onNext()
   }
}

А потом:

var difficultyView = DifficultyView()

difficultyView.levelDidDecrease.asObservable()
    .subscribe(onNext: {
        print("did decrease")
    })
    .addDisposableTo(disposeBag)


difficultyView.decreaseLevel(theSender) // <- THIS line performs the side effect
person xandrefreire    schedule 22.01.2017
comment
decreaseLevel(:) функция будет вызываться при нажатии на связанный IBOutlet. - person xandrefreire; 22.01.2017
comment
Круто, спасибо за указатели. Но зачем создавать DifficultyViewType, а не просто использовать свойства PublishSubject? - person Aymen Rebouh; 22.01.2017
comment
Вам не нужно создавать DifficultyViewType, если вы не хотите применять такое поведение в других подпредставлениях. - person xandrefreire; 22.01.2017
comment
Я обновил ответ, удалив протокол DifficultyViewType. - person xandrefreire; 22.01.2017
comment
Идея мне нравится, спасибо. Является ли он заменой стандартного кода делегата и протокола в проекте, над которым вы работаете? - person Aymen Rebouh; 22.01.2017
comment
да. Я предпочитаю использовать свой собственный код. Я бы использовал прокси-решение, чтобы красиво инкапсулировать реализации делегирования системы в Rx. - person xandrefreire; 23.01.2017