fix
无故事王国
2024-03-04 54c6ef0be42d9f2e49a344fd69f231cb6df43797
WanPai/ViewModel/RefreshModel.swift
@@ -1,9 +1,9 @@
    //
    //  RefreshModel.swift
    //  WanPai
    //
    //  Created by 无故事王国 on 2023/7/11.
    //
//
//  RefreshModel.swift
//  WanPai
//
//  Created by 无故事王国 on 2023/7/11.
//
import UIKit
import MJRefresh
@@ -13,187 +13,267 @@
enum RefreshState {
    case refreshing
    case completedRefresh
    case moreLoading
    case completedLoad
    case completedLoadWithNoMoreData
            case refreshing
            case completedRefresh
            case moreLoading
            case completedLoad
            case completedLoadWithNoMoreData
}
protocol RefreshModelProctol {
    associatedtype T:HandyJSON
    func api()->(Observable<BaseResponse<[T]>>)?
            associatedtype T:HandyJSON
            func api()->(Observable<BaseResponse<[T]>>)?
}
protocol RefreshModelInnerProctol {
            associatedtype T:HandyJSON
            func api()->(Observable<BaseResponse<BaseResponseList<T>>>)?
}
class RefreshModel<T:HandyJSON>:RefreshModelProctol{
    func api() -> (RxSwift.Observable<BaseResponse<[T]>>)? {
        return nil
    }
            func api() -> (RxSwift.Observable<BaseResponse<[T]>>)? {return nil}
            let disposeBag = DisposeBag()
            enum RefreshType {case refresh,load}
    let disposeBag = DisposeBag()
            private var handle:UIScrollView!
            lazy var refreshSubject = PublishSubject<RefreshState>()
            var page:Int = 0
            var pageSize:Int = 20
            private var needRefreshData:Bool = true
            lazy var dataSource = BehaviorRelay<[T]>(value: [])
            func configure(_ scrollView:UITableView,needMore:Bool = true){
                        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
                        if needMore{
                                    scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
                        }
                        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
                        handle = scrollView
            }
            func configure(_ scrollView:UICollectionView,needMore:Bool = true,needRefreshData:Bool = true){
                        self.needRefreshData = needRefreshData
                        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
                        if needMore{
                                    scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
                        }
                        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
                        handle = scrollView
            }
            func beginRefresh(){
                        handle.mj_header?.beginRefreshing()
            }
            func refreshData() ->(()->Void) {
                        return {self.request(status: .refresh)}
            }
            func loadMoreData() ->(()->Void) {
                        return {self.request(status: .load)}
            }
            func request(status:RefreshType){
                        switch status {
                                    case .refresh:
                                                self.page = 1
                                                self.refreshSubject.onNext(.refreshing)
                                    case .load:
                                                self.page += 1
                                                self.refreshSubject.onNext(.moreLoading)
                        }
                        api()?.subscribe(onNext: { data in
                                    if let datas = data.data{
                                                switch status{
                                                            case .refresh:
                                                                        self.dataSource.accept(datas)
                                                                        self.refreshSubject.onNext(.completedRefresh)
                                                            case .load:
                                                                        self.dataSource.accept(self.dataSource.value + datas)
                                                                        if datas.count == 0{
                                                                                    self.refreshSubject.onNext(.completedLoadWithNoMoreData)
                                                                        }else{
                                                                                    self.refreshSubject.onNext(.completedLoad)
                                                                        }
                                                }
                                    }else{
                                                self.refreshSubject.onNext(.completedLoadWithNoMoreData)
                                    }
                        }, onError: { error in
                                    self.refreshSubject.onNext(.completedLoad)
                        }).disposed(by: disposeBag)
            }
}
    enum RefreshType {
        case refresh,load
    }
class RefreshInnerModel<T:HandyJSON>:RefreshModelInnerProctol{
            func api() -> (RxSwift.Observable<BaseResponse<BaseResponseList<T>>>)? {
                        return nil
            }
            let disposeBag = DisposeBag()
            enum RefreshType {case refresh,load}
            private var handle:UIScrollView!
            lazy var refreshSubject = PublishSubject<RefreshState>()
            var page:Int = 0
            var pageSize:Int = 20
            private var needRefreshData:Bool = true
            lazy var dataSource = BehaviorRelay<BaseResponseList<T>?>(value: nil)
            func configure(_ scrollView:UITableView,needMore:Bool = true){
                        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
                        if needMore{
                                    scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
                        }
                        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
                        handle = scrollView
            }
            func configure(_ scrollView:UICollectionView,needMore:Bool = true,needRefreshData:Bool = true){
                        self.needRefreshData = needRefreshData
                        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
                        if needMore{
                                    scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
                        }
                        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
                        handle = scrollView
            }
            func beginRefresh(){
                        handle.mj_header?.beginRefreshing()
            }
            func refreshData() ->(()->Void) {
                        return {self.request(status: .refresh)}
            }
            func loadMoreData() ->(()->Void) {
                        return {self.request(status: .load)}
            }
            func request(status:RefreshType){
                        switch status {
                                    case .refresh:
                                                self.page = 1
                                                self.refreshSubject.onNext(.refreshing)
                                    case .load:
                                                self.page += 1
                                                self.refreshSubject.onNext(.moreLoading)
                        }
                        api()?.subscribe(onNext: { data in
                                    switch status{
                                                case .refresh:
                                                            self.dataSource.accept(data.data)
                                                            self.refreshSubject.onNext(.completedRefresh)
                                                case .load:
                                                            var new = self.dataSource.value?.list ?? []
                                                            new.append(contentsOf: data.data?.list ?? [])
                                                            var model = self.dataSource.value
                                                            model!.list = new
                                                            self.dataSource.accept(model)
                                                            if data.data?.list.count == 0{
                                                                        self.refreshSubject.onNext(.completedLoadWithNoMoreData)
                                                            }else{
                                                                        self.refreshSubject.onNext(.completedLoad)
                                                            }
                                    }
                        }, onError: { error in
                                    self.refreshSubject.onNext(.completedLoad)
                        }).disposed(by: disposeBag)
            }
    private var handle:UIScrollView!
    lazy var refreshSubject = PublishSubject<RefreshState>()
    var page:Int = 0
    var pageSize:Int = 20
   private var needRefreshData:Bool = true
    lazy var dataSource = BehaviorRelay<[T]>(value: [])
    func configure(_ scrollView:UITableView,needMore:Bool = true){
        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
        if needMore{
            scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
        }
        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
        handle = scrollView
    }
   func configure(_ scrollView:UICollectionView,needMore:Bool = true,needRefreshData:Bool = true){
      self.needRefreshData = needRefreshData
        scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
        if needMore{
            scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
        }
        refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
        handle = scrollView
    }
    func beginRefresh(){
        handle.mj_header?.beginRefreshing()
    }
    func refreshData() ->(()->Void) {
        return {self.request(status: .refresh)}
    }
    func loadMoreData() ->(()->Void) {
        return {self.request(status: .load)}
    }
    func request(status:RefreshType){
        switch status {
            case .refresh:
                self.page = 1
                self.refreshSubject.onNext(.refreshing)
            case .load:
                self.page += 1
                self.refreshSubject.onNext(.moreLoading)
        }
        api()?.subscribe(onNext: { data in
            if let datas = data.data{
                switch status{
                    case .refresh:
                        self.dataSource.accept(datas)
                        self.refreshSubject.onNext(.completedRefresh)
                    case .load:
                        self.dataSource.accept(self.dataSource.value + datas)
                  if datas.count == 0{
                     self.refreshSubject.onNext(.completedLoadWithNoMoreData)
                  }else{
                     self.refreshSubject.onNext(.completedLoad)
                  }
                }
            }else{
                self.refreshSubject.onNext(.completedLoadWithNoMoreData)
            }
        }, onError: { error in
            self.refreshSubject.onNext(.completedLoad)
        }).disposed(by: disposeBag)
    }
}
class CustomRefreshHeaer:MJRefreshNormalHeader{
    static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshNormalHeader? {
        let refreshHeader = MJRefreshNormalHeader(refreshingBlock: refreshingBlock)
        return refreshHeader
    }
            static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshNormalHeader? {
                        let refreshHeader = MJRefreshNormalHeader(refreshingBlock: refreshingBlock)
                        return refreshHeader
            }
}
class CustomRefreshFooter:MJRefreshAutoNormalFooter{
    static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshAutoNormalFooter? {
        let refrehFooter = MJRefreshAutoNormalFooter(refreshingBlock: refreshingBlock)
        refrehFooter.isRefreshingTitleHidden = true
      refrehFooter.stateLabel?.isHidden = true
        return refrehFooter
    }
            static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshAutoNormalFooter? {
                        let refrehFooter = MJRefreshAutoNormalFooter(refreshingBlock: refreshingBlock)
                        refrehFooter.isRefreshingTitleHidden = true
                        refrehFooter.stateLabel?.isHidden = true
                        return refrehFooter
            }
}
extension Reactive where Base : UITableView {
    func handlestatus() -> Binder<RefreshState> {
        return Binder(self.base) { (tableView, status) in
            switch status {
                case .moreLoading:
                    self.base.mj_footer?.beginRefreshing()
                case .refreshing:
                    self.base.reloadData()
                    self.base.mj_footer?.resetNoMoreData()
                    self.base.mj_header?.beginRefreshing()
            func handlestatus() -> Binder<RefreshState> {
                        return Binder(self.base) { (tableView, status) in
                                    switch status {
                                                case .moreLoading:
                                                            self.base.mj_footer?.beginRefreshing()
                                                case .refreshing:
                                                            self.base.reloadData()
                                                            self.base.mj_footer?.resetNoMoreData()
                                                            self.base.mj_header?.beginRefreshing()
                case .completedLoadWithNoMoreData:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
               (self.base.mj_footer as? MJRefreshAutoNormalFooter)?.stateLabel?.isHidden = false
                    self.base.mj_footer?.endRefreshingWithNoMoreData()
                    self.base.mj_header?.endRefreshing()
                case .completedLoad:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
                    self.base.mj_footer?.endRefreshing()
                    self.base.mj_header?.endRefreshing()
                default:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
                    self.base.mj_header?.endRefreshing()
                    self.base.mj_footer?.endRefreshing()
            }
        }
    }
                                                case .completedLoadWithNoMoreData:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            (self.base.mj_footer as? MJRefreshAutoNormalFooter)?.stateLabel?.isHidden = false
                                                            self.base.mj_footer?.endRefreshingWithNoMoreData()
                                                            self.base.mj_header?.endRefreshing()
                                                case .completedLoad:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            self.base.mj_footer?.endRefreshing()
                                                            self.base.mj_header?.endRefreshing()
                                                default:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            self.base.mj_header?.endRefreshing()
                                                            self.base.mj_footer?.endRefreshing()
                                    }
                        }
            }
}
extension Reactive where Base : UICollectionView {
    func handlestatus() -> Binder<RefreshState> {
        return Binder(self.base) { (tableView, status) in
            switch status {
                case .moreLoading:
                    self.base.mj_footer?.beginRefreshing()
                case .refreshing:
                    self.base.reloadData()
                    self.base.mj_footer?.resetNoMoreData()
                    self.base.mj_header?.endRefreshing()
            func handlestatus() -> Binder<RefreshState> {
                        return Binder(self.base) { (tableView, status) in
                                    switch status {
                                                case .moreLoading:
                                                            self.base.mj_footer?.beginRefreshing()
                                                case .refreshing:
                                                            self.base.reloadData()
                                                            self.base.mj_footer?.resetNoMoreData()
                                                            self.base.mj_header?.endRefreshing()
                case .completedLoadWithNoMoreData:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
                    self.base.mj_footer?.endRefreshingWithNoMoreData()
                case .completedLoad:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
                    self.base.mj_footer?.endRefreshing()
                default:
                    DispatchQueue.main.async {
                        self.base.reloadData()
                    }
                    self.base.mj_header?.endRefreshing()
                    self.base.mj_footer?.endRefreshing()
            }
        }
    }
                                                case .completedLoadWithNoMoreData:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            self.base.mj_footer?.endRefreshingWithNoMoreData()
                                                case .completedLoad:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            self.base.mj_footer?.endRefreshing()
                                                default:
                                                            DispatchQueue.main.async {
                                                                        self.base.reloadData()
                                                            }
                                                            self.base.mj_header?.endRefreshing()
                                                            self.base.mj_footer?.endRefreshing()
                                    }
                        }
            }
}