如何比对AddItem列表,为未入库对象设置added属性标记Realm已存项
批量标记已存在条目的实现方案
性能优先的匹配逻辑
如果直接用两层嵌套循环遍历两个列表做比对,数据量稍大就会触发主线程卡顿。正确的做法是提前从已入库列表提取所有唯一标识生成集合,利用集合的O(1)哈希查找能力,把整体匹配效率提升到线性级别。
具体实现步骤
- 从数据库拉取完成已保存的
addList后,第一时间遍历提取所有条目的id字段,生成对应类型的Set - 基于网络拉取的Station数据构建临时AddItem列表时,直接判断当前Station的id是否存在于已入库id集合中
- 因为
added属性是RealmOptional<Bool>类型,赋值时需要传入布尔值初始化对应的RealmOptional实例,不能直接用普通Bool赋值
调整后的可运行代码
func setAddItemList(stations: [Station], sensors: [Sensor]) { var addItems = [AddItem]() var sensorItems = [SensorItem]() // 获取数据库中已保存的关注列表 addList = try persistenceService.fetchAddItems().toArray(ofType: AddItem.self) // 提取已入库条目的所有id,生成Set做快速匹配 let savedItemIdSet = Set(addList.map { $0.id }) let addItem = stations.map { station in // 判断当前条目是否已在数据库中 let isExistInDB = savedItemIdSet.contains(station.id) return AddItem( id: station.id, stationId: station.id, cityName: station.city?.name ?? "", addressStreet: station.addressStreet!, added: RealmOptional<Bool>(isExistInDB), sensor: []) } addItems.append(contentsOf: addItem) }
开发注意点
- 优先选择全局唯一的
id作为匹配依据,不要依赖名称、地址这类可能存在重复的文本字段做匹配,避免出现标记错误 - 若需要做多字段联合校验,可以在生成Set时把多字段拼接为唯一字符串(例如
id_城市名_街道地址)存储,比对时用相同规则拼接临时列表的字段做查找即可 - 所有标记逻辑要在TableView渲染前的列表构建阶段一次性完成,不要在
cellForRowAt代理方法里实时做查找,避免列表滚动卡顿
内容的提问来源于stack exchange,提问作者beginner992
相关产品推荐
相关产品推荐

