You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:03:30