拜读YYKit微博篇

最近看了看YY微博的实现,用小本子记了记笔记。
先上一个简略的流程图:


拜读YYKit微博篇_第1张图片
图1.png
  • 首先后台线程异步的去请求数据(从JSON文件取),初始化WBStatusLayout类来接受数据,然后根据数据计算好业务所需要的布局信息(这个类就是核心类),这个工作结束后回到主线程刷新UITableView。
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    for (int i = 0; i <= 7; i++) {
    NSData *data = [NSData dataNamed:[NSString stringWithFormat:@"weibo_%d.json",i]];
    WBTimelineItem *item = [WBTimelineItem modelWithJSON:data];
    for (WBStatus *status in item.statuses) {
    WBStatusLayout *layout = [[WBStatusLayout alloc] initWithStatus:status style:WBLayoutStyleTimeline];
    [_layouts addObject:layout];
    }
    }

      // 复制一下,让列表长一些,不至于滑两下就到底了
      [_layouts addObjectsFromArray:_layouts];
      
      dispatch_async(dispatch_get_main_queue(), ^{
          self.title = [NSString stringWithFormat:@"Weibo (loaded:%d)", (int)_layouts.count];
          [indicator removeFromSuperview];
          self.navigationController.view.userInteractionEnabled = YES;
          [_tableView reloadData];
      });
    

    });

  • 下面这个方法就是WBStatusLayout类根据存储图片数据的个数来布局“9宫格图片。WBStatusLayout会计算出每个 cell的高度和相关布局信息缓存下来。这样再次滑动UITableView直接从缓存里面提取就好了,并不会再次计算。

   - (void)_layoutPicsWithStatus:(WBStatus *)status isRetweet:(BOOL)isRetweet {
   if (isRetweet) {
    _retweetPicSize = CGSizeZero;
    _retweetPicHeight = 0;
   } else {
    _picSize = CGSizeZero;
    _picHeight = 0;
   }
    if (status.pics.count == 0) return;

     CGSize picSize = CGSizeZero;
     CGFloat picHeight = 0;

     CGFloat len1_3 = (kWBCellContentWidth + kWBCellPaddingPic) / 3 - kWBCellPaddingPic;
     len1_3 = CGFloatPixelRound(len1_3);
     switch (status.pics.count) {
    case 1: {
        WBPicture *pic = _status.pics.firstObject;
        WBPictureMetadata *bmiddle = pic.bmiddle;
        if (pic.keepSize || bmiddle.width < 1 || bmiddle.height < 1) {
            CGFloat maxLen = kWBCellContentWidth / 2.0;
            maxLen = CGFloatPixelRound(maxLen);
            picSize = CGSizeMake(maxLen, maxLen);
            picHeight = maxLen;
        } else {
            CGFloat maxLen = len1_3 * 2 + kWBCellPaddingPic;
            if (bmiddle.width < bmiddle.height) {
                picSize.width = (float)bmiddle.width / (float)bmiddle.height * maxLen;
                picSize.height = maxLen;
            } else {
                picSize.width = maxLen;
                picSize.height = (float)bmiddle.height / (float)bmiddle.width * maxLen;
            }
            picSize = CGSizePixelRound(picSize);
            picHeight = picSize.height;
        }
    } break;
    case 2: case 3: {
        picSize = CGSizeMake(len1_3, len1_3);
        picHeight = len1_3;
    } break;
    case 4: case 5: case 6: {
        picSize = CGSizeMake(len1_3, len1_3);
        picHeight = len1_3 * 2 + kWBCellPaddingPic;
    } break;
    default: { // 7, 8, 9
        picSize = CGSizeMake(len1_3, len1_3);
        picHeight = len1_3 * 3 + kWBCellPaddingPic * 2;
    } break;
   }

    if (isRetweet) {
    _retweetPicSize = picSize;
    _retweetPicHeight = picHeight;
    } else {
    _picSize = picSize;
    _picHeight = picHeight;
   }
   }
  • 通过下面协议方法去给Cell相关信息。非常简洁。
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellID = @"cell";
    WBStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (!cell) {
    cell = [[WBStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    cell.delegate = self;
    }
    [cell setLayout:_layouts[indexPath.row]];
    return cell;
    }

YY的代码真心写的非常的漂亮。特别是把Cell所有的事件通过WBStatusCellDelegate代理进行统一的管理,提高了代码的可读性。

  /// 点击了 Cell
  - (void)cellDidClick:(WBStatusCell *)cell;
  /// 点击了 Card
  - (void)cellDidClickCard:(WBStatusCell *)cell;
  /// 点击了转发内容
  - (void)cellDidClickRetweet:(WBStatusCell *)cell;
  /// 点击了Cell菜单
  - (void)cellDidClickMenu:(WBStatusCell *)cell;
  /// 点击了关注
  - (void)cellDidClickFollow:(WBStatusCell *)cell;
  /// 点击了转发
  - (void)cellDidClickRepost:(WBStatusCell *)cell;
  /// 点击了下方 Tag
  - (void)cellDidClickTag:(WBStatusCell *)cell;
  /// 点击了评论
  - (void)cellDidClickComment:(WBStatusCell *)cell;
 /// 点击了赞
  - (void)cellDidClickLike:(WBStatusCell *)cell;
  /// 点击了用户
 - (void)cell:(WBStatusCell *)cell didClickUser:(WBUser *)user;
  /// 点击了图片
- (void)cell:(WBStatusCell *)cell didClickImageAtIndex:(NSUInteger)index;
/// 点击了 Label 的链接
- (void)cell:(WBStatusCell *)cell didClickInLabel:(YYLabel *)label textRange:(NSRange)textRange;

在这里我只是简略的去做了一个梳理。如果您有兴趣可以去github上下载下来读读源码。
YYkit github : https://github.com/ibireme/YYKit

你可能感兴趣的:(拜读YYKit微博篇)