无法从自定义视图传递 RxSwift PublishRelay 值

Can't pass the RxSwift PublishRelay value from custom view

我正在尝试使用 rx 操作扩展我的 KeyboardView 视图,但没有成功。根据断点调试,值被传递给中继,但尽管在视图控制器中有进一步的订阅,但不会调用扩展。可能是什么问题以及如何解决?

final class KeyboardView: UIView {

    private let disposeBag = DisposeBag()
    
    fileprivate let buttonTappedRelay = PublishRelay<ActionType>()
    
    private let digitButtons: [KeyboardButton] = {
        return stride(from: 0, through: 9, by: 1)
            .compactMap { [=10=] }
            .map { KeyboardButton(actionType: .digit([=10=])) }
    }()
    
    private let eraseButton: KeyboardButton = {
        let button = KeyboardButton(actionType: .erase)
        return button
    }()
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupViews()
        setupConstraints()
        setupActions()
    }
    
    private func setupViews() { ... }
    
    private func setupConstraints() { ... }
    
    private func setupActions() {
        eraseButton.rx.buttonTap
            .asObservable()
            .observeOn(MainScheduler.instance)
            .subscribe(onNext: { [weak self] actionType in
                self?.buttonTappedRelay.accept(actionType)
            }).disposed(by: self.disposeBag)
        
        for button in digitButtons {
            button.rx.buttonTap
                .asObservable()
                .observeOn(MainScheduler.instance)
                .subscribe(onNext: { [weak self] actionType in
                    self?.buttonTappedRelay.accept(actionType)
                }).disposed(by: self.disposeBag)
        }
    }
    
}

extension Reactive where Base: KeyboardView {
    
    internal var buttonTap: ControlEvent<ActionType> {
        return ControlEvent<ActionType>(events: base.buttonTappedRelay.asObservable() )
    }
    
}

您的问题可能出在您未显示的代码中。请注意,以下代码编译、运行和工作:

final class KeyboardView: UIView {

    private let disposeBag = DisposeBag()

    fileprivate let buttonTappedRelay = PublishRelay<ActionType>()

    private let digitButtons: [KeyboardButton] = {
        return stride(from: 0, through: 9, by: 1)
            .compactMap { [=10=] }
            .map { KeyboardButton(actionType: .digit([=10=])) }
    }()

    private let eraseButton: KeyboardButton = {
        let button = KeyboardButton(actionType: .erase)
        return button
    }()

    public override init(frame: CGRect) {
        super.init(frame: frame)

        setupViews()
        setupActions()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupViews() {
        let stack = UIStackView(frame: bounds)
        stack.distribution = .equalSpacing
        stack.addArrangedSubview(eraseButton)
        for each in digitButtons {
            stack.addArrangedSubview(each)
        }
        addSubview(stack)
    }

    private func setupActions() {
        eraseButton.rx.buttonTap
            .asObservable()
            .observeOn(MainScheduler.instance)
            .subscribe(onNext: { [weak self] actionType in
                self?.buttonTappedRelay.accept(actionType)
            }).disposed(by: self.disposeBag)

        for button in digitButtons {
            button.rx.buttonTap
                .asObservable()
                .observeOn(MainScheduler.instance)
                .subscribe(onNext: { [weak self] actionType in
                    self?.buttonTappedRelay.accept(actionType)
                }).disposed(by: self.disposeBag)
        }
    }

}

final class ViewController: UIViewController {
    weak var keyboard: KeyboardView?

    override func loadView() {
        super.loadView()
        let keyboard = KeyboardView(frame: view.bounds)
        view.addSubview(keyboard)
        self.keyboard = keyboard
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        keyboard!.rx.buttonTap
            .debug("")
            .subscribe()
    }
}

extension Reactive where Base: KeyboardView {

    internal var buttonTap: ControlEvent<ActionType> {
        return ControlEvent<ActionType>(events: base.buttonTappedRelay.asObservable() )
    }
}

enum ActionType {
    case digit(Int)
    case erase
}

class KeyboardButton: UIButton {
    let actionType: ActionType
    init(actionType: ActionType) {
        self.actionType = actionType
        super.init(frame: CGRect.zero)
        backgroundColor = .red
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension Reactive where Base: KeyboardButton {
    var buttonTap: Observable<ActionType> {
        base.rx.tap.map { base.actionType }
    }
}