Я реализовал табличное представление с пользовательскими ячейками, содержащими UITextField. В нижнем колонтитуле у меня есть кнопка «Продолжить», которая становится доступной, когда все текстовые поля заполнены. Проблема в том, что когда я заполняю все текстовые поля, иногда кнопка не обновляет состояние isEnabled без вывода табличного представления, что вы можете увидеть на видео:
Есть предложения? Спасибо!
Это моя реализация ячейки:
import UIKit
import RxSwift
import RxCocoa
class CompleteInputDataCell:UITableViewCell {
var bag = DisposeBag()
static let cellIdentifier = "completeDataCellIdentifier"
@IBOutlet weak var fieldNameTitle:UILabel!
@IBOutlet weak var textField:CustomTextField!
var vm:CompleteInputDataCellViewModelProtocol? {
didSet {
oldValue?.dispose()
self.bindUI()
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.bindUI()
}
override func prepareForReuse() {
super.prepareForReuse()
self.bag = DisposeBag()
}
private func bindUI() {
guard let vm = self.vm else { return }
vm.cellStyle.observeOn(MainScheduler.asyncInstance).bind { (style) in
self.contentView.backgroundColor = style.backgroundColor
self.textField.backgroundColor = style.textFieldBackgroundColor
self.textField.defaultTextAttributes = style.textFieldTextAttributes
}.disposed(by: vm.bag)
Observable.combineLatest(vm.titleText, vm.cellStyle).map { (text, style) -> NSAttributedString? in
return text?.toAttributed(attributes: style.textFieldTitleAttributes)
}.bind(to: self.fieldNameTitle.rx.attributedText).disposed(by: vm.bag)
Observable.combineLatest(vm.textFieldPlaceholderText, vm.cellStyle).map { (text, style) -> NSAttributedString? in
return text?.toAttributed(attributes: style.textFieldPlaceholderAttributes)
}.observeOn(MainScheduler.asyncInstance).bind(onNext: { [weak self] (text) in
self?.textField.attributedPlaceholder = text
}).disposed(by: vm.bag)
self.textField.rx.text.bind(to: vm.inputText).disposed(by: vm.bag)
}
}
Это мой класс textField:
import Foundation
import UIKit
class CustomTextField:UITextField {
let padding = UIEdgeInsets(top: 20, left: 16, bottom: 16, right: 20)
override func awakeFromNib() {
super.awakeFromNib()
layer.cornerRadius = 8
textColor = UIColor.DoveGray
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: self.padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: self.padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: self.padding)
}
}
И таким образом я привязываю обновление состояния кнопки:
vm.isContinueButtonEnabled().observeOn(MainScheduler.asyncInstance).bind(onNext: {[weak self] (value) in
value ? self?.continueButton.setCurrent(state: .enabled) : self?.continueButton.setCurrent(state: .disabled)
}).disposed(by: vm.bag)
Этот метод определяет, все ли текстовые поля заполнены, и если да, возвращает true, что означает, что кнопка продолжения активирована:
override func isContinueButtonEnabled() -> Observable<Bool> {
do {
let elements = try self.dataSource.value().filter({ (type) -> Bool in
switch type {
case .InputCell(_, _):
return true
default:
return false
}
}).map({ (type) -> BehaviorSubject<String?> in
switch type {
case .InputCell(let vmProtocol, _):
return vmProtocol.inputText
default:
let text = CompleteInputDataCellVM().inputText
text.onNext("dfs")
return text
}
})
return Observable.combineLatest(elements).map { (values) -> Bool in
var isEnabled = true
values.forEach { (value) in
isEnabled = isEnabled && (value != nil) && (value != "")
}
return isEnabled
}
} catch {
return BehaviorSubject<Bool>(value: false)
}
}