如何通过 Today Extension (iOS 8) 访问 Core Data/CloudKit

Posted

技术标签:

【中文标题】如何通过 Today Extension (iOS 8) 访问 Core Data/CloudKit【英文标题】:How to access Core Data/CouldKit via Today Extension (iOS8) 【发布时间】:2015-08-16 20:12:20 【问题描述】:

我有一个应用程序在 AppDelegate 中使用 Core Data 和标准 Apple Core Data 堆栈。我已经修改了堆栈,以便使用 CloudKit 增强 Core Data。所有数据都很好地在所有设备上同步。到目前为止一切顺利。

我想在我的应用程序中添加 Today Extension,但我不知道如何访问数据。我一直在阅读有关 AppGroup 概念的信息,但我也读到我不应该/不能使用它来访问 Today Extension 中的数据。所以我想我应该使用 CloudKit,因为我了解到 NSManagedObjects 在上传到 iCloud 时会转换为 CKRecords。

如何通过 iCloud 访问 Core Data 使用 CloudKit 增强存储的数据? 这些数据究竟存储在 iCloud 中的什么位置?

虽然所有数据都很好地同步,但当我签入 iCloud 仪表板时,似乎没有数据存在。我阅读的所有 SO 文章似乎只解决了我的部分问题。

这是我在应用程序中使用的修改后的核心数据堆栈:

    // MARK: - Core Data stack

lazy var managedObjectModel: NSManagedObjectModel = 
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
    let modelURL = NSBundle.mainBundle().URLForResource("AppName", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
    ()

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = 
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store
    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

    let documentDirectory = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last as! NSURL

    let storeUrl = documentDirectory.URLByAppendingPathComponent("AppName.sqlite")

    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."

    let storeOptions = [NSPersistentStoreUbiquitousContentNameKey:"ItemsCloudStore"]

    let url = storeUrl

    if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: storeOptions, error: &error) == nil 
        coordinator = nil
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason
        dict[NSUnderlyingErrorKey] = error
        error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(error), \(error!.userInfo)")
        abort()
    

    return coordinator
    ()

lazy var managedObjectContext: NSManagedObjectContext? = 
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil 
        return nil
    


            var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)

    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
    ()


// MARK: - Core Data Saving support
func saveContext () 
    if let moc = self.managedObjectContext 
        var error: NSError? = nil
        if (moc.hasChanges && !moc.save(&error)) 

            println("Unresolved error \(error), \(error!.userInfo)")
            abort()

         else 

            println("Context was updated")
        
    

【问题讨论】:

您是否尝试过从扩展程序访问数据? 是的。但是,当我使用 AppGroups 以便从应用程序和扩展程序访问时,我失去了 iCloud 功能。我无法使用 CloudKit 和上面的代码从扩展中访问数据。现在我正在将所有核心数据的东西移到一个框架中。不确定这是否是我应该采取的方法,或者它是否有机会成功。 【参考方案1】:

经过一些研究,这似乎是 Apple 未解决的问题。 Core Data 和 iCloud 不能与 Extensions 一起使用。看看这篇文章:

https://devforums.apple.com/message/1050891#1050891

有点遗憾。希望他们至少在 ios9 中修复它。

【讨论】:

不幸的是,该链接似乎不再有效。

以上是关于如何通过 Today Extension (iOS 8) 访问 Core Data/CloudKit的主要内容,如果未能解决你的问题,请参考以下文章

iOS Today Extension 能否从应用的 Info.plist 中读取 URL 方案

iOS 8 Today Extension:是不是可以添加可编辑的文本字段?

iOS扩展Extension之Today

iOS开发------Widget(Today Extension)插件化开发

如何在 Today Extension 中显示资产目录中的图像?

iOS - SharedApplication 在 Today Extension 中不可用?