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

如何对比两个含自定义Swift对象的数组并按ID去重添加?

解决数组对比与UserDefaults存储问题

你的核心需求其实分为两部分:将API返回的新数据合并到本地数组中,以及把最终数组持久化到UserDefaults。先从你的数组对比逻辑说起,再补充UserDefaults的实现细节。

一、数组对比逻辑的优化与验证

你写的contains(where:)逻辑本身是正确的,但可能因为两个原因导致没达到预期:

  1. lenders数组初始为空,没有从UserDefaults读取已有数据,导致每次都直接添加所有temp对象;
  2. LenderData的id类型不匹配(比如一个是String一个是Int),或者id的取值有问题。

先给你优化后的合并逻辑,用Set来提升查找效率(尤其是数组元素较多时):

private func mergeNewLenders() {
    // 先把已有lenders的id存入Set,O(1)查找效率
    let existingLenderIds = Set(lenders.map { $0.id })
    // 过滤出temp中不存在于已有数组的对象
    let newLenders = lendersTemp.filter { !existingLenderIds.contains($0.id) }
    // 批量添加新对象
    lenders.append(contentsOf: newLenders)
}

如果你的数组元素不多,原来的循环写法也完全可以用,核心是确保$0.id == tempLender.id的对比是有效的。

二、UserDefaults存储的完整实现

要把自定义类型LenderData存入UserDefaults,必须让它遵循Codable协议(这是Swift中序列化/反序列化自定义对象的标准方式):

1. 修改LenderData结构

struct LenderData: Codable {
    let id: String // 或者Int,根据你的API返回类型调整
    // 这里添加你的其他属性,比如name、address等
}

2. 实现UserDefaults的读写方法

在你的ViewController中添加两个私有方法,负责读取和存储数组:

private func loadLendersFromUserDefaults() {
    guard let savedData = UserDefaults.standard.data(forKey: "SavedLenders") else {
        lenders = []
        return
    }
    do {
        // 反序列化数据为LenderData数组
        lenders = try JSONDecoder().decode([LenderData].self, from: savedData)
    } catch {
        print("读取本地数据失败: \(error.localizedDescription)")
        lenders = []
    }
}

private func saveLendersToUserDefaults() {
    do {
        // 序列化数组为Data类型
        let dataToSave = try JSONEncoder().encode(lenders)
        UserDefaults.standard.set(dataToSave, forKey: "SavedLenders")
        // iOS 10+后自动同步,这里加上更保险
        UserDefaults.standard.synchronize()
    } catch {
        print("保存数据到本地失败: \(error.localizedDescription)")
    }
}

3. 在viewDidLoad中整合流程

调整你的viewDidLoad,把读取、下载、合并、存储的流程串起来:

var lenders = [LenderData]()
var lendersTemp = [LenderData]()

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 第一步:先从UserDefaults读取已存储的本地数据
    loadLendersFromUserDefaults()
    
    // 第二步:下载API数据,完成后合并并存储
    downloadJSON {
        self.mergeNewLenders()
        self.saveLendersToUserDefaults()
        self.myTableView.reloadData()
    }
    
    self.myTableView.rowHeight = 90
    myTableView.delegate = self
    myTableView.dataSource = self
}

三、常见问题排查

如果还是没达到预期,可以检查这几点:

  • 确认LenderData的所有属性都符合Codable要求(比如没有自定义的非Codable类型);
  • 打印tempLender.id和已有lenders中对象的id,确认对比逻辑正确;
  • 在saveLendersToUserDefaults后,打印UserDefaults.standard.data(forKey: "SavedLenders"),确认数据确实被存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:50:14