MVVM + RxSwift

👌. MVVM + RxSwift + CTMediatror + MJRefresh + DZNEmptyDataSet

Build responsive data binding infrastructure based on MVVM + RxSwift

CatHome

  • Resource module, mainly processing picture resources and text resources read

    • Read image resources:R.image("base_black_back")
    • Read text resources:R.text("base_empty_title")
    • Read the color resource:R.color("background")

BeeBox

  • The main collection of RxSwift related easy method classes

Adapter

  • This module mainly encapsulates base classes
    • BaseViewController: Supports oc base classes, common part
    • VMTableViewController: List base class, internal reactive processing
    • VMViewController: The base class must be specified for inheritanceViewModelOr a subclass of a generic that automatically lazily loads VM objects of the specified type.
    • ViewModel: The base model that subclasses must inherit from

CTMediatror

  • This module mainly solves the problem that Swift adopts the componentized scheme CocoaPods
extension CTMediator {
    // Swift dispatcher
    func Second_viewController(title: String)- > (UIViewController?). {let params = [
            "title": title,
            kCTMediatorParamsKeySwiftTargetModuleName: "Rickenbacker_Example"
        ] as [AnyHashable : Any]
        let viewController = self.performTarget(String(describing: SecondViewController.self),
                                                action: "Extension_ViewController",
                                                params: params,
                                                shouldCacheTarget: false) as? UIViewController
        return (viewController)
    }
}

class Target_SecondViewController: NSObject {
    /// note that '@objc' must be added here
    /// Otherwise the method cannot be found and the controller becomes' nil '
    @objc func Action_Extension_ViewController(_ params: NSDictionary) -> UIViewController? {
        guard let title = params["title"] as? String else { return nil }
        let vc = SecondViewController.init()
        vc.viewModel = SecondViewModel.init(title: title)
        return vc
    }
}
Copy the code

HBDNavigationBar

  • The module is based on the HBDNavigationBar secondary encapsulation of the underlying navigation bar

MJRefresh

  • This module is based on the MJRefresh encapsulation list refresh function
final class MJRefreshViewModel: ViewModel {
    struct Input {
        let headerRefresh: Observable<Void>
        let footerRefresh: Observable<Void>}struct Output {
        let items: Driver"[String] >}}extension MJRefreshViewModel: ViewModelType {
    func transform(input: Input) -> Output {
        var objects: [String] = []
        var page: Int = 1
        
        /// Drop refresh
        let refresh = input.headerRefresh.then(page = 1)
            .flatMapLatest {
                MJRefreshAPI.refresh(page).request()
            }.map { [unowned self] (items) -> [String] in
                refreshSubject.onNext(.endHeaderRefresh)
                objects = items
                return objects
            }.asDriver(onErrorJustReturn: [])
        
        /// Pull up to load more
        let more = input.footerRefresh.then(page + = 1)
            .flatMapLatest {
                MJRefreshAPI.refresh(page).request()
            }.map { [unowned self] (items) -> [String] in
                if items.isEmpty {
                   refreshSubject.onNext(.endFooterRefreshWithNoData)
                } else {
                    refreshSubject.onNext(.endFooterRefresh)
                }
                objects + = items
                return objects
            }.asDriver(onErrorJustReturn: [])
            
        /// Data response
        let items = Driver.of(refresh, more).merge()
        /// empty data binding
        items.map { $0.isEmpty }.asObservable().bind(to: isEmptyData).disposed(by: disposeBag)
        return Output(items: items)
    }
}
Copy the code

DZNEmptyDataSet

  • This module is based on EmptyDataSet-Swift encapsulation list empty data display function
let driver = NetworkService().randomResult().asObservable()
driver.map { $0.isEmpty }.bind(to: isEmptyData).disposed(by: disposeBag)
Copy the code

CocoaPods Install

Currently, there are seven modules as follows:

  • Import the project responsive base class module:pod 'Rickenbacker/Adapter'
  • Import resource module:pod 'Rickenbacker/CatHome'
  • Import the collection module:pod 'Rickenbacker/BeeBox'
  • Import componentized modules:pod 'Rickenbacker/CTMediatror'
  • Import navigation bar basic module:pod 'Rickenbacker/HBDNavigationBar'
  • Import automatic refresh module:pod 'Rickenbacker/MJRefresh'
  • Import empty data automatic display module:pod 'Rickenbacker/DZNEmptyDataSet'

Feel helpful old brothers, please help point a star ⭐..

Save the kids. Thank you, bosses.

🥺

The last

  • Attached is the transfer RickenbackerDemo address.
  • There is also a development accelerator KJCategoriesDemo at 🎷 and if you like, you can click 🌟

✌ ️.