Я новичок в RxSwift.Это довольно сложно.
Я создаю как ToDoList, что представления, которые являются tableView и представлением add-item, разделены TabBarController.Я успешно отобразил массив списков и добавил новый элемент в tableView.
Я также хотел отобразить количество подсчетов массива и счетчиков избранных в представлении, имеющем tableView, чтобы я отобразил его, выдав значениес .just
.
Но при отображении значения на основе результата массива, отображаемого с помощью SearchBar, значение не отражается, как я ожидал.
В MainViewModel,Я удостоверился, что смогу правильно подсчитать количество массивов на print
, но, видимо, значение было в порядке.Он просто не отражается в представлении.
// Модель
struct Item: Codable {
var name = String()
var detail = String()
var tag = String()
var memo = String()
var fav = Bool()
var cellNo = Int()
init(name: String, detail: String, tag: String, memo: String, fav: Bool, celllNo: Int) {
self.name = name
self.detail = detail
self.tag = tag
self.memo = memo
self.fav = fav
self.cellNo = celllNo
}
init() {
self.init(
name: "Apple",
detail: "ringo",
tag: "noun",
memo: "",
fav: false,
celllNo: 0
)
}
}
struct SectionModel: Codable {
var list: [Item]
}
extension SectionModel: SectionModelType {
var items: [Item] {
return list
}
init(original: SectionModel, items: [Item]) {
self = original
self.list = items
}
}
Класс общего доступа Singleton
final class Sharing {
static let shared = Sharing()
var items: [Item] = [Item()]
var list: [SectionModel] = [SectionModel(list: [Item()])] {
didSet {
UserDefault.shared.saveList(list: list)
}
}
let listItems = BehaviorRelay<[SectionModel]>(value: [])
}
extension Sharing {
func calcFavCount(array: [Item]) -> Int {
var count = 0
if array.count > 0 {
for i in 0...array.count - 1 {
if array[i].fav {
count += 1
}
}
}
return count
}
}
// MainTabViewController
class MainTabViewController: UIViewController {
@IBOutlet weak var listTextField: UITextField!
@IBOutlet weak var tagTextField: UITextField!
@IBOutlet weak var itemCountLabel: UILabel!
@IBOutlet weak var favCountLabel: UILabel!
@IBOutlet weak var favIcon: UIImageView!
@IBOutlet weak var infoButton: UIButton!
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!
private lazy var viewModel = MainTabViewModel(
searchTextObservable: searchTextObservable
)
private let disposeBag = DisposeBag()
private var dataSource: RxTableViewSectionedReloadDataSource<SectionModel>!
override func viewDidLoad() {
super.viewDidLoad()
setupTableViewDataSource()
tableViewSetup()
listDetailSetup()
}
// create Observable searchBar.text to pass to ViewModel
var searchTextObservable: Observable<String> {
let debounceValue = 200
// observable to get the incremental search text
let incrementalTextObservable = rx
.methodInvoked(#selector(UISearchBarDelegate.searchBar(_:shouldChangeTextIn:replacementText:)))
.debounce(.milliseconds(debounceValue), scheduler: MainScheduler.instance)
.flatMap { [unowned self] _ in Observable.just(self.searchBar.text ?? "") }
// observable to get the text when the clear button or enter are tapped
let textObservable = searchBar.rx.text.orEmpty.asObservable()
// merge these two above
let searchTextObservable = Observable.merge(incrementalTextObservable, textObservable)
.skip(1)
.debounce(.milliseconds(debounceValue), scheduler: MainScheduler.instance)
.distinctUntilChanged()
return searchTextObservable
}
func setupTableViewDataSource() {
dataSource = RxTableViewSectionedReloadDataSource<SectionModel>(configureCell: {(_, tableView, indexPath, item) in
let cell = tableView.dequeueReusableCell(withIdentifier: "ListCell") as! ListCell
cell.selectionStyle = .none
cell.backgroundColor = .clear
cell.configure(item: item)
return cell
})
}
func tableViewSetup() {
tableView.rx.itemDeleted
.subscribe {
print("delete")
}
.disposed(by: disposeBag)
viewModel.dispItems.asObservable()
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
func listDetailSetup() {
viewModel.itemCountObservable
.bind(to: itemCountLabel.rx.text)
.disposed(by: disposeBag)
viewModel.favCountObservable
.bind(to: favCountLabel.rx.text)
.disposed(by: disposeBag)
}
}
MainTabViewModel
final class MainTabViewModel {
private let disposeBag = DisposeBag()
private let userDefault: UserDefaultManager
var dispItems = BehaviorRelay<[SectionModel]>(value: [])
private let shared = Sharing.shared
// lazy var itemCount = shared.list[0].list.count
// lazy var favCount = shared.calcFavCount
var itemCountObservable: Observable<String>
var favCountObservable: Observable<String>
init(searchTextObservable: Observable<String>,
userDefault: UserDefaultManager = UserDefault()) {
self.userDefault = userDefault
let initialValue = shared.list
shared.listItems.accept(initialValue)
dispItems = shared.listItems
// this part is to display the initil number -> success
var itemCount = shared.list[0].list.count
itemCountObservable = .just(itemCount.description + " items")
var favCount = shared.calcFavCount(array: shared.list[0].list)
favCountObservable = .just(favCount.description)
// this part is based on the searching result -> failure
searchTextObservable.subscribe(onNext: { text in
if text.isEmpty {
let initialValue = self.shared.list
self.shared.listItems.accept(initialValue)
self.dispItems = self.shared.listItems
}else{
let filteredItems: [Item] = self.shared.list[0].list.filter {
$0.name.contains(text)
}
let filteredList = [SectionModel(list: filteredItems)]
self.shared.listItems.accept(filteredList)
self.dispItems = self.shared.listItems
itemCount = filteredItems.count
self.itemCountObservable = .just(itemCount.description + " items")
favCount = self.shared.calcFavCount(array: filteredItems)
self.favCountObservable = .just(favCount.description)
print("\(itemCount) items") // the ideal number is in but not shown in the view
}
})
.disposed(by: disposeBag)
}
}
Я удалил ненужный код, но в основном вставил целый код для вашего понимания.
Надеюсь, вы могли бы помочь мне.
Спасибо.