Swift 4中如何访问Realm模型列表过滤并优化代码实现
优化Realm章节过滤与去重的实现方案
首先,我们来拆解你的需求:根据Services中ibp_service_filter的启用状态,筛选对应的IBPChapters,同时避免重复添加。你的现有代码存在嵌套循环冗余、手动去重效率低的问题,我们可以利用Realm的原生查询能力来大幅简化实现。
核心思路
Realm支持关联查询和列表元素直接过滤,不需要手动遍历每个章节再检查服务;去重则可以借助Realm查询结果的唯一性,或者用主键ID构建Set快速判断重复。
方案1:通用场景(筛选所有包含启用服务的章节)
如果你的需求是:只要章节包含任意一个ibp_service_filter为true的服务,就将其加入数组且不重复,直接用Realm的关联查询即可:
func addData() { // 1. 获取所有启用的服务(ibp_service_filter为true) let enabledServices = realm.objects(Services.self).filter("ibp_service_filter == true") // 2. 查询所有包含至少一个启用服务的章节 // Realm会自动处理去重,因为每个IBPChapters有唯一主键ibp_chapter_id let filteredChapters = realm.objects(IBPChapters.self).filter("service IN %@", enabledServices) // 3. 转成数组赋值 ibpArray = Array(filteredChapters) }
这个方案完全替代了嵌套循环,效率更高,且天然避免重复。
方案2:按特定服务/索引过滤(匹配你的需求场景)
如果需要针对特定服务(比如"legal aid"或"counseling")单独过滤,或者按列表索引判断(比如检查service[0]的启用状态),可以用以下方式:
场景1:筛选包含"legal aid"且该服务启用的章节
func addLegalAidChapters() { // 先找到启用的"legal aid"服务对象 guard let legalAidService = realm.objects(Services.self) .filter("service == 'legal aid' AND ibp_service_filter == true").first else { ibpArray.removeAll() return } // 查询所有包含该服务的章节 ibpArray = Array(realm.objects(IBPChapters.self).filter("service CONTAINS %@", legalAidService)) }
场景2:追加包含"counseling"且该服务启用的章节(不重复)
func appendCounselingChapters() { guard let counselingService = realm.objects(Services.self) .filter("service == 'counseling' AND ibp_service_filter == true").first else { return } // 获取所有包含counseling的章节 let counselingChapters = realm.objects(IBPChapters.self).filter("service CONTAINS %@", counselingService) // 用Set存储已有章节的主键,快速判断重复 let existingChapterIds = Set(ibpArray.map { $0.ibp_chapter_id }) // 过滤出未添加的章节并追加 let newChapters = counselingChapters.filter { !existingChapterIds.contains($0.ibp_chapter_id) } ibpArray.append(contentsOf: newChapters) }
按列表索引过滤(比如检查service[0]是否启用)
Realm支持直接通过索引访问列表元素进行查询,比如要筛选service列表第一个元素启用的章节:
let chapters = realm.objects(IBPChapters.self) .filter("service.@count > 0 AND service[0].ibp_service_filter == true")
对你现有代码的优化点说明
- 冗余判断移除:
chapter.service.contains(filteredServices[service_index!])完全没必要,因为filteredServices本身就是从chapter.service过滤得到的,必然包含。 - 避免嵌套循环:Realm的查询引擎比手动遍历高效得多,尤其是数据量较大时。
- 高效去重:用主键ID构建
Set判断重复,时间复杂度是O(1),比ibpArray.contains(where:...)的O(n)高效很多。
内容的提问来源于stack exchange,提问作者jpcarts23
相关产品推荐
相关产品推荐

