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

Core Data数据存储问题:无法保存/加载titles与bodys数组

Hey Matt, let's figure out why your Core Data save/load isn't working—there are a few key issues in your code that we can fix right away.

First, Let's Break Down the Problems

1. You're Not Persisting Changes to Disk

Your saveCoreData method deletes old data and creates a new entity, but you never call context.save()! All your changes only live in memory and disappear when the app closes. This is the biggest reason your data isn't sticking around.

2. Loading Logic Ignores Half Your Data

In loadCoreData, you use else if to pull title and body from each Saved entity:

if let title = result.value(forKey: "title") as? String {
    titles.append(title)
} else if let body = result.value(forKey: "body") as? String {
    bodys.append(body)
}

This means each entity only contributes either a title or a body to your arrays, not both. Since you want pairs of title/body, you need to fetch both properties from each entity.

3. You're Not Saving All Your Array Data

Your save code only creates one Saved entity, but you have entire titles and bodys arrays to store. You need to loop through both arrays and create an entity for each title-body pair.

4. Potential Thread Safety Risks

Core Data's viewContext is tied to the main thread. If loadAPIData runs in a background thread, directly accessing the context can cause crashes or data corruption.


Fixed Code Examples

Updated saveCoreData Method

func saveCoreData() {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    
    // Delete existing data first
    let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Saved")
    let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetch)
    
    do {
        try context.execute(deleteRequest)
        context.reset() // Refresh context to reflect deletion
    } catch {
        print("Failed to delete old data: \(error)")
        return
    }
    
    // Make sure arrays are the same length to avoid mismatched pairs
    guard titles.count == bodys.count else {
        print("Titles and bodys arrays don't match in length!")
        return
    }
    
    // Save every title-body pair as a new Saved entity
    for index in 0..<titles.count {
        let savedEntity = NSEntityDescription.insertNewObject(forEntityName: "Saved", into: context)
        savedEntity.setValue(titles[index], forKey: "title")
        savedEntity.setValue(bodys[index], forKey: "body")
    }
    
    // Critical: Save changes to disk
    do {
        try context.save()
        print("Core Data saved successfully!")
    } catch {
        print("Failed to save Core Data: \(error)")
    }
}

Updated loadCoreData Method

func loadCoreData() {
    // Clear existing array data first to avoid duplicates
    titles.removeAll()
    bodys.removeAll()
    
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    
    // Use a typed fetch request for better safety
    let request = NSFetchRequest<Saved>(entityName: "Saved")
    request.returnsObjectsAsFaults = false
    
    do {
        let results = try context.fetch(request)
        for result in results {
            // Fetch both title and body from each entity
            if let title = result.value(forKey: "title") as? String {
                titles.append(title)
            }
            if let body = result.value(forKey: "body") as? String {
                bodys.append(body)
            }
        }
        print("Loaded \(titles.count) items from Core Data")
    } catch {
        print("Failed to load Core Data: \(error)")
    }
}

Bonus Tips

  • Generate NSManagedObject Subclasses: Go to Xcode's Editor > Create NSManagedObject Subclass... for your Saved entity. This lets you use dot syntax like result.title instead of value(forKey:), which is safer and easier to read.
  • Thread Safety: If loadAPIData runs in a background thread, wrap Core Data calls in the main thread:
    DispatchQueue.main.async {
        self.saveCoreData()
        // or self.loadCoreData()
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:45:36