Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 防止第一响应者在tableview重新加载时辞职_Ios_Swift_Rx Swift_Rxdatasources - Fatal编程技术网

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

Ios 防止第一响应者在tableview重新加载时辞职,ios,swift,rx-swift,rxdatasources,Ios,Swift,Rx Swift,Rxdatasources,我正在使用RxSwift,目前,我有一个可以内联编辑的地址列表 例如:用户点击一个按钮,单元格转换为编辑模式,基本上显示几个UITextFields 现在的问题是,当我将文本字段的输入绑定到我的模型时,TableView会被重新加载,因此键盘会被关闭,我也尝试过RxAnimatableDataSource,但没有效果,它仍然会在每次击键时关闭键盘 视图模型: class UpdateAddressViewModel: ViewModel, ViewModelType { str

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

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

现在的问题是,当我将文本字段的输入绑定到我的模型时,TableView会被重新加载,因此键盘会被关闭,我也尝试过RxAnimatableDataSource,但没有效果,它仍然会在每次击键时关闭键盘

视图模型:

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, index, 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
            }
    }
}

您需要断开导致表视图更新的流与更改地址的流的连接

例如:

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]>
}
typealias ID=Int//示例
typealias Address=String//可能需要更多的参与。
结构输入{
让updateAddress:可见
}
结构输出{
let细胞:可见
let地址:可观察
}
表视图将被绑定到
单元格
,而每个单元格将被绑定到
地址
,可通过压缩映射来提取其特定信息

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


在my.

中可以找到一个完整的示例。您需要断开导致表视图更新的流与更改地址的流的连接

例如:

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]>
}
typealias ID=Int//示例
typealias Address=String//可能需要更多的参与。
结构输入{
让updateAddress:可见
}
结构输出{
let细胞:可见
let地址:可观察
}
表视图将被绑定到
单元格
,而每个单元格将被绑定到
地址
,可通过压缩映射来提取其特定信息

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


在我的中可以找到一个完整的例子。

是的,这完全有效!不过,我采取了与您的应用程序不同的方法,因为我的ViewModels功能没有向ViewController公开。但是这个想法本身就行。是的,这完全行得通!不过,我采取了与您的应用程序不同的方法,因为我的ViewModels功能没有向ViewController公开。但这个想法本身是可行的。