【问题标题】:How to get ObjectID and search for specific ObjectID in CoreData in Swift 5?如何在 Swift 5 的 CoreData 中获取 ObjectID 并搜索特定的 ObjectID?
【发布时间】:2020-07-20 21:53:32
【问题描述】:

我目前正在开发一个带有多用户系统的项目。用户可以使用 CoreData 创建永久保存的新配置文件。

我的问题是:一次只能激活一个配置文件,所以我想获取创建的配置文件的 ObjectID 并将其保存到用户默认值

此外,我在想,只要我需要活动配置文件的数据,我就可以简单地从 UserDefaults 获取 ObjectID 并执行 READ - Request,它只会给我返回 结果与那个特定的ObjectID

到目前为止我保存数据的代码:

// 1. Create new profile entry to the context.
let newProfile = Profiles(context: context)
newProfile.idProfileImage = idProfileImage
newProfile.timeCreated = Date()
newProfile.gender = gender
newProfile.name = name
newProfile.age = age
newProfile.weight = weight

// 2. Save the Object ID to User Defaults for "activeUser".
// ???????????????????
// ???????????????????

// 3. Try to save the new profile by saving the context to the persistent container.
do {
    try context.save()
} catch {
    print("Error saving context \(error)")
}

到目前为止我用于读取数据的代码

// 1. Creates an request that is just pulling all the data.
let request: NSFetchRequest<Profiles> = Profiles.fetchRequest()

// 2. Try to fetch the request, can throw an error.
do {
    let result = try context.fetch(request)
} catch {
    print("Error reading data \(error)")
}

如您所见,我无法实现第一个代码块的第 2 部分。新配置文件已保存,但 ObjectID 未保存到 UserDefaults。

另外第二个代码块的第一方不是最终目标。该请求只会返回该实体的所有数据,而不仅仅是我存储在用户默认值中的具有 ObjectID 的数据。

我希望你们对如何解决这个问题有一个想法。 提前感谢您的帮助!

【问题讨论】:

  • 为什么不直接向您的实体添加一个属性 isCurrent,而不是混合 UserDefaults 和 CoreData?

标签: ios swift xcode sqlite core-data


【解决方案1】:

由于NSManagedObjectID 不符合UserDefaults 处理的类型之一,您将不得不使用另一种方式来表示对象ID。幸运的是,NSManagedObjectID 有一个 uriRepresentation(),它返回一个 URL,可以存储在 UserDefaults 中。

假设您使用的是NSPersistentContainer,这里有一个扩展,它将处理活动用户Profile 的存储和检索:

extension NSPersistentContainer {
    private var managedObjectIDKey: String {
        return "ActiveUserObjectID"
    }

    var activeUser: Profile? {
        get {
            guard let url = UserDefaults.standard.url(forKey: managedObjectIDKey) else {
                return nil
            }

            guard let managedObjectID = persistentStoreCoordinator.managedObjectID(forURIRepresentation: url) else {
                return nil
            }

            return viewContext.object(with: managedObjectID) as? Profile
        }
        set {
            guard let newValue = newValue else {
                UserDefaults.standard.removeObject(forKey: managedObjectIDKey)
                return
            }

            UserDefaults.standard.set(newValue.objectID.uriRepresentation(), forKey: managedObjectIDKey)
        }
    }
}

这使用NSPersistentStoreCoordinator 上的方法从URI 表示构造NSManagedObjectID

【讨论】:

  • 非常感谢您的回答。它看起来真的很好。我完全理解 get 部分,但不知道为什么 set 部分需要这个保护语句。你能帮我澄清一下吗?
  • activeProfile 在这里被定义为可选的 ?。因此,如果您设置activeUser = nil,那么该值将从 UserDefaults 中删除。因此集合中的守卫......如果没有值(nil),则删除,如果有一个值而不是更新/设置。
  • 嗯,好的。谢谢。这是有道理的!
  • 我遇到了另一个问题。当我删除一个非活动配置文件时,该对象 ID 未保存到 UserDefaults,应用程序无法在删除后检索当前活动用户。删除另一个对象后对象 ID 是否有可能发生变化?
猜你喜欢
  • 2020-08-05
  • 2014-11-06
  • 2017-01-24
  • 2015-11-23
  • 2021-09-15
  • 1970-01-01
  • 2017-09-17
  • 2022-12-12
  • 2013-04-11
相关资源
最近更新 更多