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

Swift中API响应保存到CoreData后访问数据仍为nil如何解决

问题原因

  • 变量未初始化也未主动查询:你在ViewController中仅声明了coreGenre可选变量,没有做任何赋值操作,也没有执行CoreData的查询请求读取已存储的数据,可选变量默认值就是nil。
  • 保存逻辑存在错误:saveGenreList方法中仅创建了1个GenreList实例,遍历所有genre时反复覆盖同一个实例的name属性,最终仅会保留最后一个genre的名称;且循环内重复调用context.save(),属于不必要的冗余操作。
  • 异步执行顺序错误:API请求是异步操作,你在回调中先执行了complition回调,再执行CoreData保存逻辑,如果在complition中直接读取CoreData数据,此时保存还未执行,必然读取不到数据。
  • 未主动刷新UI:就算数据保存和读取都正常,你也没有在数据更新后调用tableView.reloadData()刷新列表,UI不会自动更新。

解决方案

1. 修正CoreData保存逻辑

首先调整保存逻辑的执行顺序,避免重复覆盖和冗余保存,如果你的业务是要存储多个分类名称,建议将CoreData实体调整为单个Genre对应一条数据,避免单条实例反复覆盖的问题:

func saveGenreList(json: GenreListModel){
    let context = persistentContainer.viewContext
    // 可选:先清空旧数据,避免重复存储
    let deleteRequest = NSBatchDeleteRequest(fetchRequest: Genre.fetchRequest())
    do {
        try context.execute(deleteRequest)
    } catch {
        print("清空旧分类数据失败:\(error)")
    }
    // 遍历创建多个Genre实例
    json.genres?.forEach({ genre in
        let newGenre = Genre(context: context)
        newGenre.name = genre.name
    })
    // 统一执行一次保存即可
    do {
        try context.save()
    } catch {
        print("保存分类数据失败:\(error)")
    }
}

同时调整API回调的执行顺序,先保存数据再执行回调:

case .success(let genreListData) :
    CoreData.shared.saveGenreList(json: genreListData) // 先保存
    complition(genreListData) // 再执行回调

2. ViewController新增CoreData查询逻辑

在ViewController中新增从CoreData读取数据的方法,读取完成后刷新列表:

// 改用数组存储多条分类数据
var coreGenres: [Genre] = []

func fetchGenreData() {
    let context = CoreData.shared.persistentContainer.viewContext
    do {
        coreGenres = try context.fetch(Genre.fetchRequest())
        // 确保UI刷新在主线程执行
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    } catch {
        print("读取分类数据失败:\(error)")
    }
}

// 调整列表行数计算逻辑
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return coreGenres.count
}

3. 触发数据读取

在两个时机触发读取逻辑:

  • ViewController生命周期方法viewWillAppear中调用fetchGenreData(),进入页面时自动读取已缓存的数据
  • 在API请求的complition回调中调用fetchGenreData(),新数据保存后主动刷新最新数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:27:01