Как получить данные, указав идентификатор (UUID) в той же модели CoreData?

В настоящее время я разрабатываю приложение с использованием SwiftUI.

Я хочу создать функцию для получения некоторых данных в CoreData модели с идентификатором в той же CoreData модели.


Это пример функции, которую я хочу создать (не работает, просто для объяснения)

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

Это работает вот так.


Моя цель - отобразить некоторые task данные в виде списка в WIdget, используя id данные, когда Widget получают данные выборки.

(Как значения для отображения в списке и теги для присвоения значения selection, когда мы используем picker)

Вот код:

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


person Tio    schedule 07.01.2021    source источник
comment
если у меня есть эта модель CoreData ... - где она называется, как получить к ней доступ? любой запрос на выборку?   -  person pawello2222    schedule 08.01.2021
comment
Вам нужно использовать NSPredicate с вашим запросом на выборку. Если вы опубликуете более подробную информацию о своей модели, кто-нибудь, вероятно, сможет помочь вам выяснить, как настроить предикат.   -  person Tom Harrington    schedule 08.01.2021
comment
@ pawello2222, @ Tom Harrington, Спасибо за комментарий, я обновил свой вопрос.   -  person Tio    schedule 08.01.2021
comment
Что getDataById делает?   -  person Pranav Kasetti    schedule 08.01.2021
comment
@Pranav Kasetti, getDataById получает id в модели, а затем возвращает task в той же строке в той же модели.   -  person Tio    schedule 08.01.2021


Ответы (1)


Что вам нужно, так это связь между двумя объектами.

Решение №1 - Основные данные

Вы можете создать связь между Todo и Task непосредственно на уровне основных данных. Вы не разместили достаточно подробностей в своем вопросе, чтобы подробнее рассказать об этом решении, однако вы можете следовать этим ответам:

Затем вы сможете получить Task, связанный с Todo элементом, а затем просто получить необходимые свойства непосредственно из объекта Task.

Решение №2 - Карта

Другое возможное решение - получить все Task объекты в IntentHandler, а затем сопоставить свои 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
    }
}
person pawello2222    schedule 09.01.2021
comment
Спасибо за ответ, к сожалению, произошла ошибка в написании кода ... и я только что обновил let request = NSFetchRequest<TodoEntity>(entityName: "TodoEntity") в IntentHandler.swift. собирается. Итак, в моем CoreData есть только один Entity (TodoEntity). Не могли бы вы посоветовать мне, как решить эту проблему в этом случае? Мне очень жаль мою ошибку. - person Tio; 10.01.2021
comment
Наконец, я смог отобразить значение task, используя Dictionary() и compactMap по id в том же Entity. Спасибо за вашу помощь! - person Tio; 10.01.2021