Swift 3:无需分区用双数组填充TableView实现Periscope直播效果
实现无分区的Periscope风格TableView
嘿,我来帮你搞定这个需求!不用分区完全能实现Periscope里那种混合评论和用户加入通知的效果,核心就是把两种数据合并成一个统一的数据源数组,给每个元素打上类型标记,这样TableView就能精准渲染对应的内容啦。下面一步步来:
第一步:定义数据类型枚举
先搞个枚举来区分两种消息类型,把对应的数据也存进去:
enum LiveFeedItem { case comment(content: String) // 评论内容 case userJoined(username: String) // 加入的用户昵称 }
要是你需要按时间顺序展示(直播场景肯定需要!),可以给每个case加个timestamp: Date属性,后面合并的时候好排序。
第二步:合并两个数组成统一数据源
你手里的comments和joinedUsers两个数组,直接合并成上面定义的LiveFeedItem数组就行。如果有时间戳,记得先按时间排序再合并,保证消息顺序正确:
// 先声明统一数据源 var liveFeedItems: [LiveFeedItem] = [] // 合并数据的方法 func mergeLiveData(comments: [String], joinedUsers: [String]) { // 把评论转成LiveFeedItem let commentItems = comments.map { LiveFeedItem.comment(content: $0) } // 把用户加入转成LiveFeedItem let userJoinedItems = joinedUsers.map { LiveFeedItem.userJoined(username: $0) } // 合并两个数组(如果有时间戳,这里要先排序再合并!) liveFeedItems = commentItems + userJoinedItems // 要是有时间戳,排序示例: // liveFeedItems.sort { item1, item2 in // switch (item1, item2) { // case (.comment(_, let ts1), .comment(_, let ts2)): return ts1 < ts2 // case (.userJoined(_, let ts1), .userJoined(_, let ts2)): return ts1 < ts2 // case (.comment(_, let ts1), .userJoined(_, let ts2)): return ts1 < ts2 // case (.userJoined(_, let ts1), .comment(_, let ts2)): return ts1 < ts2 // } // } }
第三步:TableView数据源实现
接下来就是TableView的常规配置,因为不用分区,所以numberOfSections直接返回1,numberOfRowsInSection返回liveFeedItems.count就行。重点在cellForRowAt里根据类型渲染不同cell:
// 先注册两种cell(提前在storyboard或者代码里注册好) tableView.register(CommentCell.self, forCellReuseIdentifier: "CommentCell") tableView.register(UserJoinedCell.self, forCellReuseIdentifier: "UserJoinedCell") // 数据源方法 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return liveFeedItems.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let item = liveFeedItems[indexPath.row] switch item { case .comment(let content): let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentCell cell.commentLabel.text = content // 这里可以配置评论cell的其他UI,比如头像、用户名等 return cell case .userJoined(let username): let cell = tableView.dequeueReusableCell(withIdentifier: "UserJoinedCell", for: indexPath) as! UserJoinedCell cell.messageLabel.text = "\(username) est là" // 配置用户加入cell的UI,比如加个小图标、调整文字样式等 return cell } }
要是你觉得搞两个cell太麻烦,也可以用一个通用cell,根据类型隐藏/显示不同的控件(比如评论显示内容标签,用户加入显示提示标签),这样更灵活。
第四步:实时更新处理(直播必备)
直播场景下肯定会有新评论或新用户加入,这时候别直接reloadData,用插入行的方式更流畅,还带动画:
// 添加新评论 func addNewComment(_ content: String) { let newIndex = liveFeedItems.count liveFeedItems.append(.comment(content: content)) tableView.insertRows(at: [IndexPath(row: newIndex, section: 0)], with: .bottom) // 自动滚动到底部显示最新消息 tableView.scrollToRow(at: IndexPath(row: newIndex, section: 0), at: .bottom, animated: true) } // 添加新加入的用户 func addNewJoinedUser(_ username: String) { let newIndex = liveFeedItems.count liveFeedItems.append(.userJoined(username: username)) tableView.insertRows(at: [IndexPath(row: newIndex, section: 0)], with: .bottom) tableView.scrollToRow(at: IndexPath(row: newIndex, section: 0), at: .bottom, animated: true) }
小优化建议
- 用自动布局让cell自适应高度,不同类型的cell可以有不同的高度;
- 如果消息量很大,可以做cell复用优化,避免内存占用过高;
- 给消息加上时间戳后,不仅能排序,还能在cell上显示发送时间,更贴近Periscope的体验。
内容的提问来源于stack exchange,提问作者Ghiggz Pikkoro
相关产品推荐
相关产品推荐

