废话开篇:最近写了一段 ApiCloud 混合开发 APP,说是混合开发,可是大部分的功能还是以 JS 为主,其实,ApiCloud 跨渠道的开发只能算是东西,而不能算是一门言语。那么,JS 本身是运转在 JS 环境中的,一般页面的 JS 运转在 WKWebView 对应的环境里。当然,也能够初始化一个 JS 运转环境,让一些自定义代码运转在这个脱离 webViewJS 运转环境里。可是,不管是以什么办法运转 JS,假如不在同一个环境下,那么,该环境下的 JS 数据在不借助桥接的情况下是不能同享的,所以,就会有人猎奇,原生开发下,详情页的数据变了,列表页面的对应UI怎么同步修正?

一、JS形式下,详情页的数据变了,列表页面的对应UI怎么同步修正?

JS 的运转及访问边界被 WKWebView 约束住了,假如不经过原生的多 WebView 之间的通讯辅助是无法做到数据同享的。

二、iOS形式下,为什么详情页的数据变了,列表页面的对应UI能够同步修正?

原生的一切的值、目标、办法,都在同一个运转环境里,假如指针传的足够远,那么,程序将会在任何地方访问或调用某些目标或办法。

三、iOS形式下,怎么做到详情页的数据变了,列表页面的对应UI能够同步修正?

完成办法其实有许多种:

1、署理回执;

2、闭包回执;

3、通知回执;

4、目标调查者回执;

上面一切办法的思路,其实都是经过“一根线”链接“两个点”,仅仅完成的办法不一样而已。

上面最好的办法还是经过目标调查者进行回执修正,这个就好比我们在过斑马线,每个人都盯着信号灯,一旦绿灯亮起,那么,我们就动起来;反之,其他的办法就类似于,张三看见绿灯亮了,告诉李四,李四告诉王五…

四、iOS形式下,简略完成

3.1 完成效果

详情页的修正“点赞”数,上一级的列表“点赞”展现数也随之变化

当有人问:详情页的数据变了,列表页面的对应UI如何同步修改?

3.2 完成思路

使用 RxSwift 调查者进行绑定

将目标的“点赞”特点分别绑定到 Cell 上面的 UILable 和详情页里的 UILable 上。那么,不管在个代码下修正了“点赞”特点值,那么,绑定的UI都会作出更改。

3.3 代码展现

这儿说一下 RxSwift 使用过程中的留意点:

新闻目标类

class NewsClass : NSObject, HandyJSON{
  @objc dynamic var thumb : Int = 0
  @objc dynamic var name : String?
  @objc dynamic var url : String?
  @objc dynamic var mineThumbStatus : Bool = false
  required override init(){
  }
  //绑定数据
  func rxBindContent(_ cell : WSLNewsListTableViewCell){
    self.rx.observeWeakly(Int.self, "thumb").asObservable().bind(to: cell.rx.thumbLab).disposed(by: cell.disposeBag)
    self.rx.observeWeakly(String.self, "name").asObservable().bind(to: cell.rx.nameLab).disposed(by: cell.disposeBag)
    self.rx.observeWeakly(String.self, "url").asObservable().bind(to: cell.rx.coverImg).disposed(by: cell.disposeBag)
  }
}

留意点1:目标需承继 NSObject,以沿用 rx 系列的扩展办法。

留意点2:关于用 RxSwiftrx.observeWeakly 调查的目标特点需要用 @objc dynamic 修饰,赋予特点动态特性。

留意点3:在绑定数据办法里,使用 bind 办法将调查序列绑定在了自定义 cellrx 相关扩展下。

赋值及其他相关的操作放在这儿,外部进进行绑定

//MARK: -扩展cell的rx特点
extension Reactive where Base : WSLNewsListTableViewCell {
  var thumbLab : Binder<Int?> {
    return Binder(self.base){ cell ,content **in**
      cell.thumbLab.text = "点赞数:" + String(describing: content!)
      cell.thumbLab.sizeToFit()
    }
  }
  var nameLab : Binder<String?> {
    return Binder(self.base){ cell ,content in
      cell.nameLab.text = content!
      cell.nameLab.sizeToFit()
    }
  }
  var coverImg : Binder<String?> {
    return Binder(self.base) { cell , url in
      cell.coverImgView.kf.setImage(with: URL(string: url ?? ""))
    }
  }
}

留意点4:这儿的绑定办法是在 UITableViewDataSource 办法里,那么,重用机制自然会导致多次绑定。

cell 的绑定赋值操作

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell : WSLNewsListTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CELL", for: indexPath) as! WSLNewsListTableViewCell
    //进行数据绑定
    models?[indexPath.row].rxBindContent(cell)
    //点击事情
    cell.enterDetailBtn.rx.controlEvent(.touchUpInside).subscribe {[weak self] btn in
      self?.pushDetailNewsVCSubject.onNext(self?.models?[indexPath.row])
    }.disposed(by: cell.disposeBag)
    return cell
  }

model 的绑定事情

func rxBindContent(_ cell : WSLNewsListTableViewCell){
    self.rx.observeWeakly(Int.self, "thumb").asObservable().bind(to: cell.rx.thumbLab).disposed(by: cell.disposeBag)
    self.rx.observeWeakly(String.self, "name").asObservable().bind(to: cell.rx.nameLab).disposed(by: cell.disposeBag)
    self.rx.observeWeakly(String.self, "url").asObservable().bind(to: cell.rx.coverImg).disposed(by: cell.disposeBag)
}

处理复用机制重复绑定数据的办法便是绑定数据的序列毁掉相关 cell.disposeBag,在 cellprepareForReuse 办法里进行 cell.disposeBag 的重置。

这儿说一下 disposed 含义:意为毁掉操作。在日常的开发中,会创立许多序列,可是,它们的生命周期交给谁处理呢?为了处理这个问题就出现了 disposed(by: disposeBag) 来辅助,把一切的序列相关到 disposeBag 上,那么,当 disposeBag 目标在某个机遇被毁掉的时分,一起毁掉它相关的一切序列。

cell 复用前进行 disposeBag 重置

override func prepareForReuse() {
    super.prepareForReuse()
    disposeBag = DisposeBag()
}

这样就保证了,屏幕上可见的 cell 才具有绑定效果。

留意点5:在详情页修正传入参数的特点值。

btn.rx.tap.subscribe {[weak self] _ in
    self?.newsClass?.thumb += 1
}.disposed(by: disposeBag)

这样就完成了详情页修正特点,列表页面UI同步修正。

五、model 目标用 struct 类型的怎么处理?

很遗憾,结构体归于值类型,在办法传入的时分会有一个副本。在逃逸闭包里,结构体更是会被复制出来,那么,假如不能操作原数据的话,扩展还有什么含义呢?

聪明的掘友会想到:是不是能够用 ReplaySubject 进行数据传递呢?由于 ReplaySubject 归于目标,即便结构体采用副本复制的办法传值,可是,关于目标类型的“特点”,复制的也是目标地址,那么,是不是能够进行直接 UI 绑定操作呢?答案是能够的! 可是这样的操作没有办法改动列表页的结构体数据,所以,不能进行数据同步,只能做到 UI 显现同步。

总结与思考:大神许多,可是这篇小总结,明显不是给大神看的[抱拳][抱拳][抱拳]。但里喜欢共享跟学习的小伙伴也许多,期望这篇小总结,对我们能起到帮助[抱拳][抱拳][抱拳]。