今日iOS扩展与核心数据 [英] iOS today extension with core data

查看:89
本文介绍了今日iOS扩展与核心数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的ios应用进行今天的扩展。
今天的扩展程序将基于与核心数据一起保存的数据显示下一个课程。
我一直在做一些研究,我知道我必须与appGroup共享我的persistentContainer。
所以我这样做了:

I am trying to make a today extension for my ios app. That today extension will display the 'next' Course based on data saved with core data. I've been doing some research and I understand I have to share my persistentContainer with an appGroup. So I did :


  • 为ios应用程序和今天的扩展目标启用了appGroup。

  • 编写了一个共享它的函数:

public extension NSPersistentContainer {
    func addToAppGroup(id: String) {
        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: id) else {
            fatalError("Shared file container could not be created.")
        }
        let storeURL = fileContainer.appendingPathComponent("\(self.name).sqlite")
        let storeDescription = NSPersistentStoreDescription(url: storeURL)
        self.persistentStoreDescriptions.append(storeDescription)
    }
}

然后在我的核心数据栈中:

then in my core data stack :

internal class CoreDataContainer {

    static var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentCloudKitContainer(name: "SchoolCompanion")
        container.addToAppGroup(id: "group.com.Ce-dricLoneux.School-Companion")
        container.loadPersistentStores(completionHandler: { (_, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        let context = CoreDataContainer.persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}

文件和xcdatamodel在两个目标之间共享。
此时,我以为可以从扩展名访问我的核心数据,但是当我执行提取请求时,没有任何结果。

that files and the xcdatamodel are shared between both targets. At this point I thought I could access my core data from my extension but when i do a fetch request I don't get any result. The controllerDidChangeContent is never executed.

class TodayViewController: UIViewController, NCWidgetProviding {
private func configureFetchedResultsController() {
        let request: NSFetchRequest<Course> = Course.fetchRequest()
        request.sortDescriptors =  []
        self.fetchedResultsController = NSFetchedResultsController<Course>(fetchRequest: request, managedObjectContext: CoreDataContainer.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
        self.fetchedResultsController.delegate = self
        do {
            try self.fetchedResultsController.performFetch()
        } catch {
            print(error.localizedDescription)
        }
    }

override func viewDidLoad() {
        super.viewDidLoad()

        self.extensionContext?.widgetLargestAvailableDisplayMode = .compact
        self.configureFetchedResultsController()

    }

func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
        // Perform any setup necessary in order to update the view.

        // If an error is encountered, use NCUpdateResult.Failed
        // If there's no update required, use NCUpdateResult.NoData
        // If there's an update, use NCUpdateResult.NewData

        completionHandler(NCUpdateResult.newData)
    }
}

// MARK: - FetchedResultsController Delegate

extension TodayViewController: NSFetchedResultsControllerDelegate {
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        print("content did change")
    }
}

我也尝试使提取请求不明确,但结果得到一个空数组。
为什么我没有得到任何结果?

I tried to make a fetch request direclty too, buti get an empty array as result. Why does I don't get any result ?

另一件事:每次从ios应用程序更新数据时,我都使用nsfetchedResult控制器来刷新视图数据,因此可以还是应该使用widgetPerformUpdate方法?在那种情况下,我们不知道今天的扩展将何时刷新,并且它可能会支付过期的数据。

Another thing : i used nsfetchedResult controller in order to refresh the view data each time the data is updated from the ios app so is that ok or should I use the widgetPerformUpdate method ? In that case we don't know when the today extension will be refreshed and it may dispay outdated data.

使用的主要文档: https://www.avanderlee.com/swift/core-data-app-extension-data-共享/

推荐答案

您应该像下面这样子类化NSPersistentCloudKitContainer,返回的应用组网址defaultDirectoryURL()。然后在您的 CoreDataStack 中,使用 let container = GroupedPersistentCloudKitContainer(name: SchoolCompanion)。同时删除对 addToAppGroup(...)的调用。您需要在应用程序和扩展程序中实例化 GroupedPersistentCloudKitContainer ,还需要确保 GroupedPersistentCloudKitContainer 链接到两个Target。

You should subclass NSPersistentCloudKitContainer like below, returning the App Group URL for defaultDirectoryURL(). Then in your CoreDataStack, use let container = GroupedPersistentCloudKitContainer(name: "SchoolCompanion"). Also remove, your call to addToAppGroup(...). You will need to instantiate the GroupedPersistentCloudKitContainer in both the App and the Extension, you will also need to make sure the GroupedPersistentCloudKitContainer is linked to both Targets.

class GroupedPersistentCloudKitContainer: NSPersistentCloudKitContainer {

    enum URLStrings: String {
        case group = "group.com.yourCompany.yourApp"
    }


    override class func defaultDirectoryURL() -> URL {
        let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: URLStrings.group.rawValue)

        if !FileManager.default.fileExists(atPath: url!.path) {
            try? FileManager.default.createDirectory(at: url!, withIntermediateDirectories: true, attributes: nil)
        }
        return url!
    }
    ...
}

这篇关于今日iOS扩展与核心数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆