基于可观测数组数据iOS RxSwift制作事件视图

w80xi6nr  于 2022-11-28  发布在  Swift
关注(0)|答案(1)|浏览(120)

嗨我准备ios开发人员
对不起,因为英语说得不好
我想知道一般如何执行。
订阅数组数据并创建自定义视图

doTableViewModel.doItems
    .observe(on: MainScheduler.instance)
    .subscribe(onNext: { viewModelItems in
        self.doTableView.reloadData(viewModelItems: viewModelItems)
        // make and draw view
        // after view create event
        self.doTableView.doItemViews.forEach{ doItemView in
            let item = doItemView.doItem
            doItemView.rx.tapGesture()
                .when(.recognized)
                .subscribe(onNext: { element in
                    print(item.doID)
                    }
                ).disposed(by: self.disposeBag)
            doItemView.checkButton.rx.tapGesture()
                .when(.recognized)
                .subscribe(onNext: { _ in
                    self.tappedDoItemCheck(viewDoItem: item)
                    }
                ).disposed(by: self.disposeBag)
            
            doItemView.deleteButton.rx.tapGesture()
                .when(.recognized)
                .subscribe(onNext: { _ in
                    self.tappedDoItemRemove(doItem: item)
                    }
                ).disposed(by: self.disposeBag)
            
            doItemView.editButton.rx.tapGesture()
                .when(.recognized)
                .subscribe(onNext: { element in
                    self.tappedDoItemEdit(doItem: item)
                    }
                ).disposed(by: self.disposeBag)
        }
        self.doTableView.configureLayer()
    })
    .disposed(by: disposeBag)

订阅......我不知道这种方式是否正确。

ccrfmcuu

ccrfmcuu1#

这是不正确的。

  • 它有保留周期。当自己拥有disposeBag时,不要在subscribe中强捕获self
  • 在subscribe call中包含subscribe call是一种代码味道。请尽量避免它。(注意,在下面的代码中,只有一个subscribe(onNext:),而不是很多。)

我更希望看到如下代码:

doTableViewModel.doItems
    .observe(on: MainScheduler.instance)
    .flatMapLatest { [doTableView] items in
        doTableView.configure(viewModelItems: items)
    }
    .subscribe(onNext: { [weak self] action in
        guard let self else { return }
        switch action {
        case let .check(doItem):
            self.tappedDoItemCheck(viewDoItem: doItem)
        case let .edit(doItem):
            self.tappedDoItemEdit(doItem: doItem)
        case let .remove(doItem):
            self.tappedDoItemEdit(doItem: doItem)
        }
    })
    .disposed(by: disposeBag)

要使上述代码正常工作,您需要将其他代码移到DoTableView和DoItemView中,如下所示:

extension DoTableView {
    enum Action {
        case check(DoItem)
        case remove(DoItem)
        case edit(DoItem)
    }

    func configure(viewModelItems: [DoItem]) -> Observable<Action> {
        reloadData(viewModelItems: viewModelItems)
        configureLayer()
        return Observable.merge(zip(doItemViews, viewModelItems).map { doItemView, doItem in
            doItemView.configure()
                .compactMap { viewAction in
                    switch viewAction {
                    case .print:
                        print(doItem.doID)
                        return nil
                    case .check:
                        return .check(doItem)
                    case .remove:
                        return .remove(doItem)
                    case .edit:
                        return .edit(doItem)
                    }
                }
        })
    }
}

extension DoItemView {
    enum Action {
        case print
        case check
        case remove
        case edit
    }

    func configure() -> Observable<Action> {
        Observable.merge(
            rx.tapGesture().when(.recognized).map { _ in Action.print },
            checkButton.rx.tapGesture().when(.recognized).map { _ in Action.check },
            deleteButton.rx.tapGesture().when(.recognized).map { _ in Action.remove },
            editButton.rx.tapGesture().when(.recognized).map { _ in Action.edit }
        )
    }
}

请注意,使用上面的代码,DoItemView不再需要doItem属性。可以删除该属性。
与RxSwift无关的一个问题是,它假设DoTableView在每次调用reloadData(viewModelItems:)方法时完全销毁并重建其DoItemView。这是非常低效的。最好使用普通的UITableView或构建您的DoTableView,以便它可以像UITableView重用其单元格一样重用DoTableView。

相关问题