当我将 RxSwift 的 DelegateProxy 与 FSCalendar 一起使用时发生错误

error occurred when I using RxSwift's DelegateProxy with FSCalendar

RxFSCalendarDelegateProxy.swift

import Foundation
import RxSwift
import RxCocoa
import FSCalendar

class RxFSCalendarDelegateProxy: DelegateProxy<FSCalendar, FSCalendarDelegate>, DelegateProxyType, FSCalendarDelegate {
    static func registerKnownImplementations() {
        self.register { (calendar) -> RxFSCalendarDelegateProxy in
            RxFSCalendarDelegateProxy(parentObject: calendar, delegateProxy: self)
        }
    }
    
    static func currentDelegate(for object: FSCalendar) -> FSCalendarDelegate? {
        return object.delegate
    }
    
    static func setCurrentDelegate(_ delegate: FSCalendarDelegate?, to object: FSCalendar) {
        object.delegate = delegate
    }
}

extension Reactive where Base: FSCalendar {
    var delegate : DelegateProxy<FSCalendar, FSCalendarDelegate> {
        return RxFSCalendarDelegateProxy.proxy(for: self.base)
    }
    
    var didSelect : Observable<Date> {
        return delegate.methodInvoked(#selector(FSCalendarDelegate.calendar(_:didSelect:at:)))
            .map({ (params) in
                return params[1] as? Date ?? Date()
            })
    }
}

MainViewController.swift

import UIKit
import ReactorKit
import FSCalendar

class MainViewController: BaseViewController, View {
    
    typealias Reactor = MainViewReactor
    
    let calendar = FSCalendar()
    let label = UILabel()
    
    init(reactor: Reactor) {
        super.init()
        defer { self.reactor = reactor }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func setupLayout() {
        self.view.addSubview(calendar)
    }
    
    override func makeConstraints() {
        
        self.calendar.snp.makeConstraints {
            [=11=].bottom.equalToSuperview()
            [=11=].top.equalToSuperview()
            [=11=].left.equalToSuperview()
            [=11=].right.equalToSuperview()
        }
    }
    
    func bind(reactor: MainViewReactor) {
        // MARK: input
        calendar.rx.didSelect.asObservable()
            .map { Reactor.Action.setDay([=11=]) }
            .bind(to: reactor.action)
            .disposed(by: disposeBag)
        // MARK: output
    }

}

我正在尝试将 FSCalendarDelegate 函数更改为 Observable 以使用 ReactorKit。 但是当我 运行 这段代码时,发生了错误 “RxCocoa/DelegateProxy.swift:230:致命错误:在隐式展开可选值时意外发现 nil” 我不知道如何修复我的 DelegateProxy。为什么 aSelector 为零?

您发现了一个错误。代码崩溃是因为 FSCalendar 询问委托是否响应选择器,但选择器是 nil。 FSCalendar 和 RxCocoa 都没有检查选择器是否为 nil。

I have submitted a pull request to the RxSwift repository to correct this problem.

在等待拉取请求通过系统时,您可以子class DelegateProxy 并覆盖有问题的方法:

class MyDelegateProxy<P: AnyObject, D>: DelegateProxy<P, D> {
    override open func responds(to aSelector: Selector!) -> Bool {
        guard aSelector != nil else { return false }
        return super.responds(to: aSelector)
    }
}

class RxFSCalendarDelegateProxy: MyDelegateProxy<FSCalendar, FSCalendarDelegate>, DelegateProxyType, FSCalendarDelegate {
    static func registerKnownImplementations() {
        self.register { (calendar) -> RxFSCalendarDelegateProxy in
            RxFSCalendarDelegateProxy(parentObject: calendar, delegateProxy: self)
        }
    }

    static func currentDelegate(for object: FSCalendar) -> FSCalendarDelegate? {
        return object.delegate
    }

    static func setCurrentDelegate(_ delegate: FSCalendarDelegate?, to object: FSCalendar) {
        object.delegate = delegate
    }
}

至于为什么aSelector是nil... 当FSCalendar要使用委托方法时,它首先检查该方法是否已经实现。如果没有,那么它会检查是否实现了该方法的弃用版本。如果没有弃用的版本,那么它将询问委托是否实现了 nil 方法。 FSCalender 这样做对我来说感觉有点傻,但显然如果这是在传统委托实现上完成的,OS 会以 false 响应。 RxCocoa 只是假设没有图书馆会这样做。