SwiftUI:如何从 Siri Intent 添加 CoreData 记录

Posted

技术标签:

【中文标题】SwiftUI:如何从 Siri Intent 添加 CoreData 记录【英文标题】:SwiftUI: How to add CoreData record from Siri Intent 【发布时间】:2021-08-10 07:59:36 【问题描述】:

我正在尝试创建一个将记录保存到 CoreData 数据库的 Intent。如果我从主应用程序运行代码,而不是在 Intent 中运行代码,则会创建记录。

代码如下:

import Intents
import CoreData
import SwiftUI

let persistenceController = PersistenceController.shared

class IntentHandler: INExtension, DiaryIntentHandling

    var moc = PersistenceController.shared.context

    override func handler(for intent: INIntent) -> Any?
    
        guard intent is DiaryIntent else
        
            fatalError("Unknwonwn intent type: \(intent)")
        
        return self
    

    func handle(intent: DiaryIntent, completion: @escaping (DiaryIntentResponse) -> Void)
    
        guard let message = message
        else
        
            completion(DiaryIntentResponse(code: .failure, userActivity: nil))
            return
        
         
        completion(DiaryIntentResponse.success(message: message))
        let context = PersistenceController.shared.container.viewContext

        let myRecord = MyRecord(context: context)
        myRecord.timestamp = Date()
        myRecord.message = message
        do 
            try context.save()
         catch 
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        

    
    
    func resolveMessage(for intent: DiaryIntent, with completion: @escaping (INStringResolutionResult) -> Void)
    
        if let message = intent.message
        
            completion(INStringResolutionResult.success(with: message))
        
        else
        
            completion(INStringResolutionResult.needsValue())
        

    
    
    public func confirm(intent: DiaryIntent, completion: @escaping (DiaryIntentResponse) -> Void) 
        completion(DiaryIntentResponse(code: .ready, userActivity: nil))
    
    

我是否需要共享对 CoreData 数据库的访问权限?如何创建记录?

【问题讨论】:

应用和意图是否都使用应用组?如果您希望应用和应用扩展共享数据,这是必要的。 如何设置应用组共享核心数据连接? 【参考方案1】:

应用扩展程序就像单独的应用程序一样工作,因此您需要设置一个应用程序“组”来在它们之间共享数据。它为您提供了一个目录,该目录不属于您的应用程序和您的应用程序扩展可以共享的应用程序沙箱的一部分。使用一个需要一些设置工作:

    通过添加组授权来启用应用组。苹果有some documentation on this。我还有一个somewhat old blog post,就设置组而言仍然准确。

    使用 Core Data 的组目录设置您的持久化容器。通常它会将数据保存在应用程序的沙箱中,但您可以告诉它使用应用程序组目录。为此,

      使用FileManager 的函数containerURL(forSecurityApplicationGroupIdentifier:) 获取目录的文件URL。该参数与您的应用组标识符相同。

      确保此目录存在!它不会自动创建。使用FileManager.default.fileExists(atPath:)检查是否存在,如果不存在,使用FileManager.default.createDirectory(at:withIntermediateDirectories:attributes:)创建。

      使用NSPersistentStoreDescription 告诉您的持久化容器使用该 URL 来存储 Core Data。就像

      let persistentContainer = NSPersistentContainer(name: containerName)
      
      let persistentStoreDescription = NSPersistentStoreDescription(url: persistentStoreUrl)
      persistentStoreDescription.type = NSSQLiteStoreType
      
      persistentContainer.persistentStoreDescriptions = [ persistentStoreDescription ]
      

    在上一步之后,持久化容器将无法找到当前在 Core Data 中的任何数据。所以:

      如果您的应用尚未发布,请将其从您的测试设备和模拟器中删除,然后重新构建。您将在应用组目录中获得一个新的持久存储。 如果您的应用已发布,请添加代码以将持久性存储从当前位置复制到新位置。在加载持久存储之前执行此操作,并且仅当应用组中的副本不存在时才执行此操作(因此您不会重新复制旧数据)。最好的方法是使用来自NSPersistentStoreCoordinatormigratePersistentStore(_:to:options:withType:) 函数。不要只是复制您的 SQLite 文件,因为这不会包含所有数据。

【讨论】:

以上是关于SwiftUI:如何从 Siri Intent 添加 CoreData 记录的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 中检测 Siri 远程滑动

在我让 iPhone 闲置后 Siri Custom Intent 停止工作

Siri Intent 请求访问令牌 OAUTH 令牌

当我询问 siri 时,我的 Intent UI 扩展不显示

尝试提交带有 Siri 扩展的应用时,来自 App Store 的“Invalid Intent Vocabulary”错误

在 xcode 中编辑 Intent 方案时,Siri Intent Query 输入字段不可用