iOS- 立即通知主应用程序中的核心数据更改的扩展程序

问题描述 投票:1回答:1

我有一个名为NSManagedObjectEvent,该代码在主机应用和今日扩展程序之间共享。 (在“目标成员身份”中,同时选中了主应用程序和小部件)。

主机应用程序和窗口小部件具有相同的应用程序组标识符,并且都共享Data Model(在目标成员身份中,同时检查了主应用程序和窗口小部件)。

当我在Xcode中启动(运行)窗口小部件时,它将显示已保存在宿主应用程序中的所有应用程序事件(Event)。但是,当我添加一个新事件时,它会出现在主机应用程序中,但不会出现在Today-widget中。如果我重新启动窗口小部件,则会显示所有事件,包括以前没有的最后一个事件。

这是获取事件的方法。它在小部件的TodayViewController中定义。

private  func fetchEvents(date: Date) {
    let predicates = NSCompoundPredicate(andPredicateWithSubpredicates: [
        NSPredicate(format: "date = %@",Date().startOfDay as CVarArg),
        NSPredicate(format: "startTime >= %@", Date() as CVarArg)
    ])
    if let ev  = try? TPEvent.fetchAll(predicates: predicates, in: persistentManager.context) {
        events = ev
    }
} 

此事件在viewWillAppearwidgetPerformUpdate中调用。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    fetchEvents(date: Date())
    self.tableView.reloadData()
}


func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
    self.fetchEvents(date: Date() )
    self.tableView.reloadData()
    completionHandler(NCUpdateResult.newData)
}

persistentManaged.contextPersistentManager.shared.context(请参见下面的代码)。

顺便说一下,当我查看Today-widget时,上述两种方法都被调用。我有很多时间弄清楚这个问题,但无法解决。

可能是什么问题以及如何解决?

[如果您需要更多信息或有任何疑问,请发表评论。

更新

我有一个单例PersistentManager。在主机应用程序和小部件中都使用viewContext

 public final class PersistentManager {

    init() {}

    public static let shared = PersistentManager()

    public lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentCloudKitContainer(name: "Event")

        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.event.data") else {
            fatalError("Shared file container could not be created.")
        }

        let storeURL = fileContainer.appendingPathComponent("Event.sqlite")
        let storeDescription = NSPersistentStoreDescription(url: storeURL)
        container.persistentStoreDescriptions = [storeDescription]

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

        container.viewContext.automaticallyMergesChangesFromParent = true

        do {
            try container.viewContext.setQueryGenerationFrom(.current)
        } catch {
            fatalError("###\(#function): Failed to pin viewContext to the current generation:\(error)")
        }

        return container
    }()

    public lazy var context = persistentContainer.viewContext

    // MARK: - Core Data Saving support
    public  func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {

                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
}
ios swift core-data today-extension
1个回答
0
投票

在iOS上发送进程间通知的一种隐藏方法是在NSUserDefaults对象上使用KVO。

NSUserDefaults.h头文件中,苹果指出

/ *!每当在当前进程中更改任何用户默认值时,都会发布NSUserDefaultsDidChangeNotification,而在普遍存在的默认值更改时或外部进程更改默认值时,则不会发布NSUserDefaultsDidChangeNotification。使用键值观察为感兴趣的特定键注册观察者将通知您所有更新,无论它们来自何处。* /

[具有此指定,可以假设通过在Combine的特定键上使用KVO(甚至在Swift上甚至是UserDefaults),值更改将从应用程序传播到扩展程序,反之亦然。

因此,方法可以是在主应用程序中的每个更改上,将更改的当前时间戳保存到UserDefaults中:

/// When the change is made in the main app:
let defaults = UserDefaults(suiteName: "group.<your bundle id>")
defaults["LastChangeTimestamp"] = Date()
defaults.synchronize()

在应用程序扩展中:

func subscribeForChangesObservation() {
    let defaults = UserDefaults(suiteName: "group.<your bundle id>")
    defaults?.addObserver(self, forKeyPath: "LastChangeTimestamp", options: [.new, .initial], context: nil)
}

override class func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    // Process your changes here.
}
© www.soinside.com 2019 - 2024. All rights reserved.