如何在同一个 CoreData 模型中通过给定 id(UUID) 来获取数据?
How to get data by giving id(UUID) in the same CoreData model?
我目前正在使用 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) | task (String)
001 | meeting
002 | shopping
003 | cooking
如果我使用如下函数:
let task = getDataById(id:001)
print(task) // meeting
它是这样工作的。
我的目标是在 Widget
获取数据时使用 id
数据在 WIdget
中将一些 task
数据显示为列表。
(当我们使用 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
您需要的是两个实体之间的关系。
解决方案 #1 - 核心数据
您可以直接在核心数据级别创建 Todo
和 Task
之间的关系。您的问题 post 没有足够的详细信息来进一步扩展此解决方案,但是,您可以遵循以下答案:
- One-to-Many and Many-to-Many Core Data Relationships
- Core Data relationships (swift)
然后,您将能够获取与 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
}
}
我目前正在使用 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) | task (String)
001 | meeting
002 | shopping
003 | cooking
如果我使用如下函数:
let task = getDataById(id:001)
print(task) // meeting
它是这样工作的。
我的目标是在 Widget
获取数据时使用 id
数据在 WIdget
中将一些 task
数据显示为列表。
(当我们使用 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
您需要的是两个实体之间的关系。
解决方案 #1 - 核心数据
您可以直接在核心数据级别创建 Todo
和 Task
之间的关系。您的问题 post 没有足够的详细信息来进一步扩展此解决方案,但是,您可以遵循以下答案:
- One-to-Many and Many-to-Many Core Data Relationships
- Core Data relationships (swift)
然后,您将能够获取与 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
}
}