美文网首页
MJRefresh使用

MJRefresh使用

作者: FallPine | 来源:发表于2018-09-14 11:20 被阅读62次
    • 模拟网络请求

    import RxSwift
    import RxCocoa
    
    class NetworkService {
        //获取随机数据
        func getRandomResult() -> Observable<[String]> {
            print("正在请求数据......")
            let items = (0 ..< 15).map {_ in
                "随机数据\(Int(arc4random()))"
            }
            let observable = Observable.just(items)
            return observable
                .delay(2, scheduler: MainScheduler.instance)
        }
    }
    
    • 对 MJRefresh 进行扩展

    import RxSwift
    import RxCocoa
    import MJRefresh
    
    extension Reactive where Base: MJRefreshComponent {
        /// 正在刷新
        var qs_refreshing: ControlEvent<Void> {
            let source: Observable<Void> = Observable.create {
                [weak control = self.base] observer -> Disposable  in
                MainScheduler.ensureExecutingOnScheduler()
                
                guard let control = control else {
                    observer.on(.completed)
                    return Disposables.create()
                }
                
                control.refreshingBlock = {
                    observer.on(.next(()))
                }
                return Disposables.create()
            }
            .takeUntil(deallocated)
            
            return ControlEvent(events: source)
        }
    }
    
    extension Reactive where Base: MJRefreshHeader {
        /// 停止头部刷新
        var qs_endHeaderRefreshing: Binder<Bool> {
            return Binder.init(base) { (header, isEnd) in
                if isEnd {
                    header.endRefreshing()
                }
            }
        }
    }
    
    extension Reactive where Base: MJRefreshFooter {
        /// 停止尾部刷新 (Bool, Bool):(是否停止刷新, 是否已经没有更多数据了)
        var qs_endFooterRefreshing: Binder<(Bool, Bool)> {
            return Binder.init(base, binding: { (footer, arg1) in
                let (isEnd, hasNoMore) = arg1
                if isEnd {
                    if hasNoMore {
                        footer.endRefreshingWithNoMoreData()
                    } else {
                        footer.endRefreshing()
                    }
                }
            })
        }
    }
    
    extension Reactive where Base: UIScrollView {
        /// 向上滚动,取消上拉
        public var qs_isUpDragging: ControlEvent<Bool> {
            let source = self.delegate.methodInvoked(#selector(UIScrollViewDelegate.scrollViewDidEndDragging(_:willDecelerate:))).map({ (_) -> Bool in
                let translation = self.base.panGestureRecognizer.translation(in: self.base.superview)
                
                if translation.y < 0 {
                    return true
                } else {
                    return false
                }
            })
            
            return ControlEvent(events: source)
        }
        
        /// 向下滚动,取消下拉
        public var qs_isDrowDragging: ControlEvent<(Bool, Bool)> {
            let source = self.delegate.methodInvoked(#selector(UIScrollViewDelegate.scrollViewDidEndDragging(_:willDecelerate:))).map({ (_) -> (Bool, Bool) in
                let translation = self.base.panGestureRecognizer.translation(in: self.base.superview)
                
                if translation.y > 0 {
                    return (true, false)
                } else {
                    return (false, false)
                }
            })
            
            return ControlEvent(events: source)
        }
    }
    
    • 实现上下拉刷新

      • ViewModel
      import RxSwift
      import RxCocoa
      
      class MJRefreshViewModel {
          //表格数据序列
          let tableData = BehaviorRelay<[String]>(value: [])
       
          //停止头部刷新状态
          let endHeaderRefreshing: Observable<Bool>
       
          //停止尾部刷新状态
          let endFooterRefreshing: Observable<(Bool, Bool)>
       
          //ViewModel初始化(根据输入实现对应的输出)
          init(tableView: UITableView, input: (
              headerRefresh: Observable<Void>,
              footerRefresh: Observable<Void>),
              dependency: (
              networkService: NetworkService,
              disposeBag:DisposeBag)) {
           
              //下拉结果序列
             let headerRefreshData = input.headerRefresh
                  .startWith(()) //初始化时会先自动加载一次数据
                  .flatMapLatest{ _ in  //也可考虑使用flatMapFirst
                      return NetworkService().getRandomResult()
                          .takeUntil(tableView.rx.qs_isUpDragging)
             }.share(replay: 1)
           
              //上拉结果序列
              let footerRefreshData = input.footerRefresh
                  .flatMapLatest{ _ in  //也可考虑使用flatMapFirst
                      return NetworkService().getRandomResult()
                          .takeUntil(tableView.rx.qs_isDrowDragging)
              }.share(replay: 1)
           
              //生成停止头部刷新状态序列
              self.endHeaderRefreshing = Observable.merge(
                  headerRefreshData.map{ _ in true },
                  tableView.rx.qs_isUpDragging.map({ (isEnd) -> Bool in
                      return isEnd
                  })
              )
      
              //生成停止尾部刷新状态序列
              self.endFooterRefreshing = Observable.merge(
                  footerRefreshData.map{ _ in (true, false) },
                  tableView.rx.qs_isDrowDragging.map({ (value) -> (Bool, Bool) in
                      return value
                  })
              )
           
              //下拉刷新时,直接将查询到的结果替换原数据
              headerRefreshData
                  .subscribe(onNext: { items in
                  self.tableData.accept(items)
              }).disposed(by: dependency.disposeBag)
           
              //上拉加载时,将查询到的结果拼接到原数据底部
              footerRefreshData
                  .subscribe(onNext: { items in
                  self.tableData.accept(self.tableData.value + items )
              }).disposed(by: dependency.disposeBag)
          }
      }
      
      • ViewController
      let disposeBag = DisposeBag()
      
      //表格
      var tableView:UITableView!
      
      override func viewDidLoad() {
          super.viewDidLoad()
       
          //创建表格视图
          self.tableView = UITableView(frame: self.view.frame, style:.plain)
          //创建一个重用的单元格
          self.tableView!.register(UITableViewCell.self,
                                   forCellReuseIdentifier: "Cell")
          self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 64, 0)
          self.view.addSubview(self.tableView!)
      
          //设置头部刷新控件
          self.tableView.mj_header = MJRefreshNormalHeader.init()
          //设置尾部刷新控件
          self.tableView.mj_footer = MJRefreshBackNormalFooter.init()
      
          //初始化ViewModel
          let viewModel = MJRefreshViewModel.init(tableView: self.tableView, input: (
              headerRefresh: self.tableView.mj_header.rx.qs_refreshing.asObservable(),
              footerRefresh: self.tableView.mj_footer.rx.qs_refreshing.asObservable()), dependency: (
                  networkService: NetworkService(),
                  disposeBag: self.disposeBag))
      
          //单元格数据的绑定
          viewModel.tableData
              .bind(to: tableView.rx.items) { (tableView, row, element) in
                  let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
                  cell.textLabel?.text = "\(row+1)、\(element)"
                  return cell
              }
              .disposed(by: disposeBag)
      
          //下拉刷新状态结束的绑定
          viewModel.endHeaderRefreshing
              .bind(to: self.tableView.mj_header.rx.qs_endHeaderRefreshing)
              .disposed(by: disposeBag)
      
          //上拉刷新状态结束的绑定
          viewModel.endFooterRefreshing
              .bind(to: self.tableView.mj_footer.rx.qs_endFooterRefreshing)
              .disposed(by: disposeBag)
      }
      

    参考文章:Swift - RxSwift的使用详解56(结合MJRefresh使用1:下拉刷新)
    Swift - RxSwift的使用详解57(结合MJRefresh使用2:上拉加载、以及上下拉组合)

    相关文章

      网友评论

          本文标题:MJRefresh使用

          本文链接:https://www.haomeiwen.com/subject/olgvgftx.html