微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

防止第一响应者在TableView重新加载时辞职

如何解决防止第一响应者在TableView重新加载时辞职

我正在使用RxSwift,目前,我有一个可以内联编辑的地址列表

IE:用户单击一个按钮,单元格就转换为编辑模式,基本上显示了几个UITextFields

现在的问题是,当我将TextField的输入绑定到我的模型时,TableView被重新加载,因此键盘关闭,我也尝试了RxAnimatableDataSource,但无济于事,它仍然在每次击键时都关闭键盘

viewmodel:

user_id | one | two 
    1   | a   | No Update

这是我的ViewController数据源到tableview的绑定

class UpdateAddressviewmodel: viewmodel,viewmodelType {
    
    struct Input {
        let viewDidLoad: AnyObserver<Void>
        let selectItemTrigger: AnyObserver<Int>
        let editButtonTrigger: AnyObserver<Int>
        let editTrigger: AnyObserver<Int>
        let firstNameIndexed: AnyObserver<(String,Int)>
        let lastNameIndexed: AnyObserver<(String,Int)>
        let address1Indexed: AnyObserver<(String,Int)>
        let address2Indexed: AnyObserver<(String,Int)>
        let zipIndexed: AnyObserver<(String,Int)>
        let cityIndexed: AnyObserver<(String,Int)>
        let stateIndexed: AnyObserver<(String,Int)>
        let phoneIndexed: AnyObserver<(String,Int)>
    }
    
    struct Output {
        let addresses: Driver<[Addressviewmodel]>
        let reloadAndScroll: Driver<(Int,Bool)>
        let showMenu: Driver<Int>
        let error: Driver<Error>
    }
    
    private(set) var input: Input!
    private(set) var output: Output!
    
    //Input
    private let viewDidLoad = PublishSubject<Void>()
    private let editButtonTrigger = PublishSubject<Int>()
    private let editTrigger = PublishSubject<Int>()
    private let firstNameIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let lastNameIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let address1Indexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let address2Indexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let zipIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let cityIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let stateIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    private let phoneIndexed = ReplaySubject<(String,Int)>.create(bufferSize: 1)
    
    //Output
    private let addresses = BehaviorRelay<[Addressviewmodel]>(value: [Addressviewmodel()])
    
    override init() {
        super.init()
        
        observeViewDidLoad()
        
        observeEditAddress()
            .bind(to: addresses)
            .disposed(by: disposeBag)
        
        firstNameIndexed
            .withLatestFrom(addresses) { firstNameIndexed,viewmodels -> (String,Int,[Addressviewmodel]) in
                let (firstName,index) = firstNameIndexed
                return (firstName,index,viewmodels)
            }
            .map { firstName,viewmodels in
                var viewmodels = viewmodels
                viewmodels[index].address.firstName = firstName
                return viewmodels
            }
            .bind(to: addresses)
            .disposed(by: disposeBag)
        
        input = Input(
            viewDidLoad: viewDidLoad.asObserver(),selectItemTrigger: selectItemTrigger.asObserver(),editButtonTrigger: editButtonTrigger.asObserver(),editTrigger: editTrigger.asObserver(),firstNameIndexed: firstNameIndexed.asObserver(),lastNameIndexed: lastNameIndexed.asObserver(),address1Indexed: address1Indexed.asObserver(),address2Indexed: address2Indexed.asObserver(),zipIndexed: zipIndexed.asObserver(),cityIndexed: cityIndexed.asObserver(),stateIndexed: stateIndexed.asObserver(),phoneIndexed: phoneIndexed.asObserver()
        )
        
        output = Output(
            addresses: addresses.asDriver(onErrorJustReturn: []),reloadAndScroll: reloadAndScroll,showMenu: editButtonTrigger.asDriverOnErrorJustComplete(),error: errorTracker.asDriver()
        )
    }
    
    private func observeViewDidLoad() {
         //Loading work here
    }
    
    private func observeEditAddress() -> Observable<[Addressviewmodel]> {
        editTrigger
            .withLatestFrom(addresses) { index,viewmodels in
                return (index,viewmodels)
            }
            .map { index,viewmodels in
                var viewmodels = viewmodels
                
                for currentIndex in viewmodels.indices {
                    viewmodels[currentIndex].isSelected = currentIndex == index
                    viewmodels[currentIndex].isEditing = currentIndex == index
                    
                    if currentIndex == index {
                        viewmodels[currentIndex].copyAddress()
                    }
                }
                
                return viewmodels
            }
    }
}

解决方法

您需要从更改地址的流中断开导致表视图更新的流。

示例可能类似于:

jq

表视图将绑定到typealias ID = Int // an example typealias Address = String // probably needs to be more involved. struct Input { let updateAddress: Observable<(ID,Address)> } struct Output { let cells: Observable<[ID]> let addresses: Observable<[ID: Address]> } ,而每个单元格都将绑定到cells,而后者可以通过compactMap观察以提取其特定信息。

这样,您可以更新特定的单元格而无需重新加载表视图中的任何单元格。

可以在我的BashFAQ #1中找到充实的示例。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。