如何利用Diffable Data Sources在TableView不同分区展示同一对象?
解决方案:让同一用户在不同分区正常显示
问题根源在于Diffable Data Source依赖Item的Hashable实现来识别唯一性,同一个AllUsersContactList对象会被判定为同一个Item,导致只会在一个分区显示。要解决这个问题,我们需要给每个Item添加分区标识,让Diffable区分同一用户在不同分区的实例。
步骤1:创建分区用户包装类型
定义一个包装结构体,将用户对象和所属分区绑定,确保同一用户在不同分区被视为不同Item:
// 先确保你的分区枚举已定义(示例) enum RecentUsersSection: CaseIterable { case recentUsers case friends } struct SectionedUser: Hashable { let user: AllUsersContactList let section: RecentUsersSection // 基于用户ID和分区生成唯一哈希值 func hash(into hasher: inout Hasher) { hasher.combine(user.userID) // 用userID作为用户唯一标识,比全属性更可靠 hasher.combine(section) } // 自定义相等判断逻辑 static func == (lhs: SectionedUser, rhs: SectionedUser) -> Bool { return lhs.user.userID == rhs.user.userID && lhs.section == rhs.section } }
步骤2:更新Diffable Data Source类型
将数据源的Item类型替换为上面的包装类型:
var dataSourceRecentUsers : UITableViewDiffableDataSource<RecentUsersSection, SectionedUser>!
步骤3:修改Cell提供逻辑
从包装类型中取出用户对象填充Cell:
func createRecentUsersDataSource(){ dataSourceRecentUsers = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { tableView, indexPath, sectionedUser in guard let cell = tableView.dequeueReusableCell(withIdentifier: "ContactsTableViewCell") as? ContactsTableViewCell else { return UITableViewCell()} let user = sectionedUser.user cell.labelName.text = user.name // 可继续设置image等其他属性 return cell }) }
步骤4:重构Snapshot生成逻辑
将原始用户数据包装成SectionedUser后再添加到对应分区:
func createRecentUserSnapShots(data : RecentUsersModel?){ var snapShot = NSDiffableDataSourceSnapshot<RecentUsersSection, SectionedUser>() snapShot.appendSections([.recentUsers,.friends]) // 转换最近用户为分区包装类型 let recentItems = data?.result?.recentUsers?.map { SectionedUser(user: $0, section: .recentUsers) } ?? [] snapShot.appendItems(recentItems, toSection: .recentUsers) // 转换好友用户为分区包装类型 let friendItems = data?.result?.friendUsers?.map { SectionedUser(user: $0, section: .friends) } ?? [] snapShot.appendItems(friendItems, toSection: .friends) dataSourceRecentUsers.apply(snapShot, animatingDifferences: true) }
可选优化:优化用户模型的Hashable实现
为了让Diffable更精准识别用户(比如用户名称/头像变化时仍能判定为同一用户),手动实现AllUsersContactList的Hashable:
struct AllUsersContactList: Codable, Hashable { let userID: Int? let name: String? let image: String? enum CodingKeys: String, CodingKey { case userID = "userId" case name, image } static func == (lhs: AllUsersContactList, rhs: AllUsersContactList) -> Bool { return lhs.userID == rhs.userID } func hash(into hasher: inout Hasher) { hasher.combine(userID) } }
内容的提问来源于stack exchange,提问作者Shivam Garg
相关产品推荐
相关产品推荐

