美文网首页
全局数据同步(二)UI篇

全局数据同步(二)UI篇

作者: 码农苍耳 | 来源:发表于2017-04-09 18:16 被阅读30次

    上次讨论了如何让数据全局同步,但是在同步到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进行。

    相关文章

      网友评论

          本文标题:全局数据同步(二)UI篇

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