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

Posted

技术标签:

【中文标题】当我将 RxSwift 的 DelegateProxy 与 FSCalendar 一起使用时发生错误【英文标题】:error occurred when I using RxSwift's DelegateProxy with FSCalendar 【发布时间】:2021-08-21 11:16:53 【问题描述】:

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 
            $0.bottom.equalToSuperview()
            $0.top.equalToSuperview()
            $0.left.equalToSuperview()
            $0.right.equalToSuperview()
        
    
    
    func bind(reactor: MainViewReactor) 
        // MARK: input
        calendar.rx.didSelect.asObservable()
            .map  Reactor.Action.setDay($0) 
            .bind(to: reactor.action)
            .disposed(by: disposeBag)
        // MARK: output
    


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

【问题讨论】:

【参考方案1】:

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

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

在等待拉取请求通过系统时,您可以继承 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 这样做对我来说有点愚蠢,但显然如果这是在传统的委托实现上完成的,操作系统会以 false 响应。 RxCocoa 只是假设没有库会这样做。

【讨论】:

以上是关于当我将 RxSwift 的 DelegateProxy 与 FSCalendar 一起使用时发生错误的主要内容,如果未能解决你的问题,请参考以下文章

ReactiveX序列——RxSwift

使用 RxSwift 的 TabelView 委托方法

ReactiveX序列——RxSwift

防止 RxSwift 中的冗余操作

RxSwift + RxRealm + RxCocoa 向 UITableView 插入行

RxSwift 更新身份验证令牌