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

如何为枚举的.loading case生成唯一标识符适配RxDataSources?

解决方案:RxDataSources中多Loading实例的IdentifiableType兼容问题

RxDataSources的差异计算依赖IdentifiableType提供的唯一identity,多个.loading实例共用同一个id会导致Diffing算法无法区分实例,进而引发UI更新异常。以下是几种可行的解决思路:

方案一:为Loading实例添加唯一标识关联值

通过给.loading case添加唯一ID关联值,确保每个Loading实例拥有独立的identity,这是最通用的解决方案。

修改后的枚举代码:

enum ViewModelType: Equatable, IdentifiableType {
    case loading(id: String)
    case post(Post)
    
    var identity: String {
        switch self {
        case .loading(let id): return id
        case let .post(post): return String(post.id)
        }
    }
    
    static func == (lhs: ViewModelType, rhs: ViewModelType) -> Bool {
        switch (lhs, rhs) {
        case (.loading(let lId), .loading(let rId)): return lId == rId
        case let (.post(l), .post(r)): return l == r
        default: return false
        }
    }
}

使用时生成唯一ID(推荐用UUID):

// 创建多个独立的Loading实例
let loadingItems = [
    ViewModelType.loading(id: UUID().uuidString),
    ViewModelType.loading(id: UUID().uuidString),
    ViewModelType.loading(id: UUID().uuidString)
]

优点:完全符合RxDataSources的要求,Diffing算法能准确计算每个实例的增删改操作;缺点:创建Loading实例时需要额外生成ID,代码量略有增加。

方案二:用序号作为Loading实例的标识

如果Loading实例的数量和位置是可控的(比如固定位置的加载项),可以用序号作为唯一标识,避免生成UUID的开销。

修改后的枚举代码:

enum ViewModelType: Equatable, IdentifiableType {
    case loading(index: Int)
    case post(Post)
    
    var identity: String {
        switch self {
        case .loading(let index): return "loading_\(index)"
        case let .post(post): return String(post.id)
        }
    }
    
    static func == (lhs: ViewModelType, rhs: ViewModelType) -> Bool {
        switch (lhs, rhs) {
        case (.loading(let lIdx), .loading(let rIdx)): return lIdx == rIdx
        case let (.post(l), .post(r)): return l == r
        default: return false
        }
    }
}

使用时指定序号:

let loadingItems = [
    ViewModelType.loading(index: 0),
    ViewModelType.loading(index: 1),
    ViewModelType.loading(index: 2)
]

优点:轻量高效,无需额外生成UUID;缺点:仅适用于Loading位置固定或序号可维护的场景,动态调整Loading数量时需要同步更新序号。

方案三:用单个实例表示多个Loading状态

如果业务上不需要单独控制每个Loading实例,可以将多个Loading合并为一个带数量参数的case,在UI层渲染对应数量的加载单元格。

修改后的枚举代码:

enum ViewModelType: Equatable, IdentifiableType {
    case loading(count: Int)
    case post(Post)
    
    var identity: String {
        switch self {
        case .loading: return "loading_group"
        case let .post(post): return String(post.id)
        }
    }
    
    static func == (lhs: ViewModelType, rhs: ViewModelType) -> Bool {
        switch (lhs, rhs) {
        case (.loading(let lCount), .loading(let rCount)): return lCount == rCount
        case let (.post(l), .post(r)): return l == r
        default: return false
        }
    }
}

UI层处理逻辑:收到.loading(count: 3)时,循环渲染3个加载单元格即可。

优点:模型结构更简洁,无需维护多个Loading实例;缺点:灵活性不足,无法单独控制单个Loading实例的状态变化。


内容的提问来源于stack exchange,提问作者Florian Ldt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:00:59