如何通过在同一 CoreData 模型中提供 id(UUID) 来获取数据?
Posted
技术标签:
【中文标题】如何通过在同一 CoreData 模型中提供 id(UUID) 来获取数据?【英文标题】:How to get data by giving id(UUID) in the same CoreData model? 【发布时间】:2021-01-07 19:30:03 【问题描述】:我目前正在使用 SwiftUI 开发应用程序。
我想创建一个函数来获取CoreData
模型中的一些数据,并在同一CoreData
模型中给出一个ID。
这是我想做的一个示例函数(不起作用,只是为了解释)
func getDataById(id:UUID) -> String // give an id in model
return task // return an task in model which has the same id of the argument
如果我有这个CoreData
模型:
id (UUID) |任务(字符串)
001 |会议
002 |购物
003 |烹饪
如果我使用如下函数:
let task = getDataById(id:001)
print(task) // meeting
它是这样工作的。
我的目标是在Widget
获取数据时使用id
数据将一些task
数据显示为WIdget
中的列表。
(当我们使用picker
时,就像在列表和标签中显示的值一样给selection
赋值)
代码如下:
IntentHandler.swift
import WidgetKit
import SwiftUI
import CoreData
import Intents
class IntentHandler: INExtension,ConfigurationIntentHandling
var moc = PersistenceController.shared.managedObjectContext
func provideNameOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: @escaping (INObjectCollection<NSString>?, Error?) -> Void)
// let request = NSFetchRequest<TimerEntity>(entityName: "TodoEntity")
let request = NSFetchRequest<TodoEntity>(entityName: "TodoEntity")
var nameIdentifiers:[NSString] = []
do
let results = try moc.fetch(request)
for result in results
nameIdentifiers.append(NSString(string: result.id?.uuidString ?? "")) // I want display task data using id data here.
catch let error as NSError
print("Could not fetch.\(error.userInfo)")
let allNameIdentifiers = INObjectCollection(items: nameIdentifiers)
completion(allNameIdentifiers,nil)
override func handler(for intent: INIntent) -> Any
return self
- 已更新 -
Persistence.swift(宿主应用)
import CoreData
import Foundation
class PersistenceController
static let shared = PersistenceController()
private init()
private let persistentContainer: NSPersistentContainer =
let storeURL = FileManager.appGroupContainerURL.appendingPathComponent("TodoEntity")
let container = NSPersistentContainer(name: "Todo")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
container.loadPersistentStores(completionHandler: storeDescription, error in
if let error = error as NSError?
print(error.localizedDescription)
)
return container
()
extension PersistenceController
var managedObjectContext: NSManagedObjectContext
persistentContainer.viewContext
extension PersistenceController
var workingContext: NSManagedObjectContext
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
context.parent = managedObjectContext
return context
extension FileManager
static let appGroupContainerURL = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.sample.Todo")!
Xcode:版本 12.0.1
ios:14.0
【问题讨论】:
"如果我有这个 CoreData 模型..." - 它在哪里调用,你如何访问它?有任何获取请求吗? 您需要在获取请求中使用NSPredicate
。如果您发布有关模型的更多详细信息,有人可能会帮助您弄清楚如何设置谓词。
@pawello2222,@Tom Harrington,感谢您的评论,我更新了我的问题。
getDataById
在做什么?
@Pranav Kasetti,getDataById
在模型中接收 id
,然后在同一模型的同一行中返回 task
。
【参考方案1】:
您需要的是两个实体之间的关系。
解决方案 #1 - 核心数据
您可以直接在核心数据级别创建Todo
和Task
之间的关系。您没有在问题中发布足够的详细信息来进一步扩展此解决方案,但是,您可以遵循以下答案:
然后,您将能够获取与 Todo
项目关联的 Task
,然后您只需直接从 Task
对象中检索必要的属性。
解决方案 #2 - 地图
另一种可能的解决方案是获取IntentHandler
中的所有Task
对象,然后将您的Todo
对象映射到获取的任务。
您可以尝试以下方法(仅作为示例,因为代码不可测试):
class IntentHandler: INExtension, ConfigurationIntentHandling
var moc = PersistenceController.shared.managedObjectContext
func provideNameOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: @escaping (INObjectCollection<NSString>?, Error?) -> Void)
var nameIdentifiers: [NSString] = []
do
// fetch todos
let todosRequest = NSFetchRequest<TodoEntity>(entityName: "TodoEntity")
let todos = try moc.fetch(todosRequest)
// fetch tasks
let tasksRequest = NSFetchRequest<TaskEntity>(entityName: "TaskEntity")
let tasks = try moc.fetch(tasksRequest)
let tasksDict = Dictionary(grouping: tasks, by: \.id)
// map `todos` to `tasks`
nameIdentifiers = todos
.compactMap todo in
guard let id = todo.id,
let task = tasksDict[id]?.first?.task
else
return nil
return NSString(string: task)
catch let error as NSError
print("Could not fetch.\(error.userInfo)")
let allNameIdentifiers = INObjectCollection(items: nameIdentifiers)
completion(allNameIdentifiers, nil)
override func handler(for intent: INIntent) -> Any
return self
【讨论】:
感谢您的回答,不幸的是,代码写错了……我现在刚刚在 IntentHandler.swift 中更新了let request = NSFetchRequest<TodoEntity>(entityName: "TodoEntity")
。被收集。所以我的CoreData
只有一个Entity
(TodoEntity)。你能告诉我在这种情况下应该如何解决吗?我很抱歉我的错误。
最后我可以在同一个id
中使用Dictionary()
和compactMap
在同一个Entity
中显示task
值,谢谢您的帮助!以上是关于如何通过在同一 CoreData 模型中提供 id(UUID) 来获取数据?的主要内容,如果未能解决你的问题,请参考以下文章