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

通过ObjectID获取Core Data记录返回nil,求代码改进方案

Fixing Core Data Permanent ObjectID Retrieval Issue

Let's break down the issues in your code and fix them step by step—your problem stems from two key mistakes in how you handle permanent IDs and how you attempt to resolve them later.


1. Critical Order Mistake in the Save Method

You're saving the context before obtaining the permanent ID, which defeats the purpose of calling obtainPermanentIDs. Once you save the context, the temporary ID might not get upgraded properly, and you're also checking the wrong condition for whether the save succeeded (you're returning isSaved as whether the ID is temporary, which is backwards).

Here's the corrected save method:

func save(completion: (Bool) -> Void) {
    guard validate() else {
        completion(false)
        return
    }
    
    do {
        // First get the permanent ID BEFORE saving the context
        try managedObjectContext.obtainPermanentIDs(for: [user])
        
        // Now save the context with the permanent ID in place
        coreDataStack.saveContext(managedObjectContext)
        
        // Verify the ID is now permanent before storing it
        let hasPermanentID = !user.objectID.isTemporaryID
        if hasPermanentID {
            UserDefaults.standard.set(user.objectID.uriRepresentation().absoluteString, forKey: Constansts.shared.kCurrentUser)
        }
        
        completion(hasPermanentID)
    } catch let error as NSError {
        print("Could not obtain permanent ID or save user. \(error.localizedDescription)")
        completion(false)
    }
}

2. Invalid Persistent Store Coordinator in Fetch Code

You're creating a brand new NSPersistentStoreCoordinator when trying to resolve the URI—but this new coordinator isn't connected to your actual persistent store file, so it can't map the URI to a valid ObjectID. Always use the coordinator already set up in your CoreDataStack.

Here's the corrected fetch code:

let coreDataStack = CoreDataStack(modelName: "MyDB")
do {
    guard let currentUserURIString = UserDefaults.standard.string(forKey: Constansts.shared.kCurrentUser),
          let objectURL = URL(string: currentUserURIString),
          // Use the existing coordinator from your CoreDataStack
          let objectID = coreDataStack.storeContainer.persistentStoreCoordinator.managedObjectID(forURIRepresentation: objectURL) else {
        fatalError("Could not find the user to create a new plan for him.")
    }
    
    let user = try coreDataStack.mainContext.existingObject(with: objectID) as! Users
    let viewController = segue.destination as! ViewController
    viewController.viewModel = NewPlanViewModel(for: user, with: coreDataStack, and: coreDataStack.mainContext)
} catch let error as NSError {
    print("Could not get current user. \(error.localizedDescription)")
}

Bonus Best Practices

  • Avoid force casting (as! Users) unless you're 100% certain the ObjectID maps to a Users object. Use as? Users and handle the nil case gracefully instead of crashing.
  • Double-check that your CoreDataStack correctly initializes the persistent store coordinator and links it to your store file—if that setup is broken, even the corrected code won't work.

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:46:06