RxSwift - как отразить количество элементов в TableView - PullRequest
0 голосов
/ 29 июня 2019

Я новичок в 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)

    }

}

Я удалил ненужный код, но в основном вставил целый код для вашего понимания.

Надеюсь, вы могли бы помочь мне.

Спасибо.

1 Ответ

0 голосов
/ 29 июня 2019

Я все равно решил эту проблему; значение было отражено.

проблема заключалась в том, что itemCountObservable был объявлен как observable и .just использовалось.

То, как работает .just, - это бросить onNext один раз, и оно завершено, что означает, что изменение, которое я сделал в searchTextObservable.subscribe(onNext~, недопустимо.

Так что я переместил itemCountObservable: Observable<String> на BehaviorRelay<String>, что только onNext выбрасывается и не завершается, тогда это работает.

Мое понимание этой проблемы заключается в том, что itemCountObservable: Observable<String> перестал выдавать значение из-за .just, как я написал выше.

Я прав ?? 1022 *

Если вы знакомы с разницей между Observable и BehaviorRelay, было бы полезно, если бы вы могли мне сказать.

Спасибо.

...