全局數據同步(二)UI篇

上次討論了如何讓數據全局同步,但是在同步到UI層的時候還是有些麻煩。現在來解決UI層的問題。

之前的方案有兩種:

  1. 在viewWillAppear的時候,reloadData,缺點是如果需要reload的數據太多,大量計算會導致阻塞主線程,雖然可能沒有那么嚴重,但是有些時候還是能夠感知出來。
  2. 使用KVO來監聽變化,缺點是代碼侵入性太強,而且嚴重影響了一些代碼的統一性。

下面是使用KVO的一個例子:

@weakify(self);
[self.KVOController observe:_record keyPath:NSStringFromSelector(@selector(praiseCount)) options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, MZRecord *object, NSDictionary<NSString *,id> * _Nonnull change) {
      @strongify(self);
      self.recordTabbar.praiseCount = object.praiseCount;
}];
[self.KVOController observe:_record keyPath:NSStringFromSelector(@selector(praised)) options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, MZRecord *object, NSDictionary<NSString *,id> * _Nonnull change) {
     @strongify(self);
     [self.recordTabbar setPraised:object.isPraised animated:self.view.window != nil];
}];
[self.KVOController observe:_record keyPath:NSStringFromSelector(@selector(collected)) options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, MZRecord *object, NSDictionary<NSString *,id> * _Nonnull change) {
    @strongify(self);
    [self.recordTabbar setCollected:object.collected animated:self.view.window != nil];
}];
[self.KVOController observe:_record keyPath:NSStringFromSelector(@selector(collectCount)) options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, MZRecord *object, NSDictionary<NSString *,id> * _Nonnull change) {
    @strongify(self);
    self.recordTabbar.collectCount = object.collectCount;
}];
[self.KVOController observe:_record keyPath:NSStringFromSelector(@selector(commentCount)) options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, MZRecord *object, NSDictionary<NSString *,id> * _Nonnull change) {
    @strongify(self);
    self.recordTabbar.commentCount = object.commentCount;
}];

上面是我們為了同步3個按鈕的狀態的代碼,我們使用了一個第三方庫來簡化KVO的編寫,但還是非常的冗余。

為此,開始思考有什么更簡單的方法。

開始我們想要封裝KVO,直接綁定數據和UI,但是很多數據并不是一一對應的,比如數字,狀態,是需要轉化的,而且狀態變更很多情況下是需要動效的,所以無論如何都不免不了監聽和轉換這兩個東西。

后來想,既然數據可以做全局同步,那么是否可以把視圖也看作一種類型的資源,也自動同步該狀態屬性呢?按照這種思路,將視圖改寫支持這種方式來同步。

@interface UIView (MZChannel) <MZChannelProtocol>
// 我們需要在創建的時候就確定類型,而且不能修改,防止意料之外的情況
- (instancetype)initWithFrame:(CGRect)frame channelType:(NSInteger)channelType;
// 加入數據池中,并且內部增加了lock,保證線程安全
- (void)bindId:(NSString *)id;
// 為了避免與view自身屬性沖突,增加了一個白名單配置
- (NSArray<NSString *> *)channelWhiteList;
@end

查看一下我們修改之后的狀態

// RecordTabbar
// 新增這兩個方法,由于之前設計中的接口與該keyPath統一,所以其他內容不需要修改
- (NSInteger)channelType {
    return MZResourceTypeNote;
}

- (NSArray<NSString *> *)channelWhiteList {
    return @[NSStringFromSelector(@selector(praised)),
             NSStringFromSelector(@selector(praiseCount)),
             NSStringFromSelector(@selector(collected)),
             NSStringFromSelector(@selector(collectCount)),
             NSStringFromSelector(@selector(commentCount))];
}
// 部分對應的setter方法
- (void)setPraised:(BOOL)praised {
    _praised = praised;
    [self.praiseButton setPraised:praised animated:self.window != nil];
}

- (void)setPraised:(BOOL)praised animated:(BOOL)animated {
    _praised = praised;
    [self.praiseButton setPraised:praised animated:animated];
}

- (void)setPraiseCount:(NSInteger)praiseCount {
    _praiseCount = praiseCount;
    self.praiseButton.praiseCount = praiseCount;
}

- (void)setCollected:(BOOL)collected {
    [self setCollected:collected animated:self.window != nil];
}

由于該頁面資源id并不會變化,所以只需要在初始化的時候綁定一次id就可以了。

[self.recordTabbar bindId:self.record.id];

這樣我們的后半部分流程(從數據到顯示)也完整了,整個流程都依賴于MZChannel進行。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,814評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 類的Static代碼塊,也就是靜態代碼塊,只會執行一次,是在類被加載的時候執行。因為每個類只會被加載一次,所以靜態...
    af4e8a35bc89閱讀 801評論 0 0
  • 所謂悲劇之二:一是不懂戲的小生毫無準備地上臺,倉促之下勇敢面對,而對白開始時卻發現他拿錯了劇本;再個是一筆一劃寫好...
    嵐風的葉子閱讀 138評論 0 0