mah*_*han 6 core-data ios swift today-extension
我有一个在主机应用程序和今天扩展之间共享的NSManagedObject调用Event。(在 Target Membership 中,主应用程序和小部件都被选中)。
宿主应用程序和小部件具有相同的应用程序组标识符并共享Data Model(在目标会员中,主应用程序和小部件都被选中)。
当我在 Xcode 中启动(运行)小部件时,它会显示Event已保存在主机应用程序中的所有应用程序事件 ( )。但是,当我添加新事件时,它会出现在主机应用程序中,但不会出现在今天的小部件中。如果我重新启动小部件,则会显示所有事件,包括之前未显示的最后一个事件。
这是获取事件的方法。它是在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
}
}
Run Code Online (Sandbox Code Playgroud)
此事件在viewWillAppear和 中调用widgetPerformUpdate。
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)
}
Run Code Online (Sandbox Code Playgroud)
persistentManaged.context是PersistentManager.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)")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是主应用程序和应用程序扩展在 iOS 上作为两个不同的进程工作。
CoreDataNotificationCenter仅在主应用程序进程中使用它发送通知。因此,您必须在此处发送进程间通知。
在 iOS 上发送进程间通知的一种隐藏方式是在UserDefaults对象上使用 KVO 。
在NSUserDefaults.h头文件中,Apple 指出
/*! NSUserDefaultsDidChangeNotification 在当前进程中任何用户默认值更改时发布,但在普遍存在的默认值更改或外部进程更改默认值时不会发布。使用键值观察为感兴趣的特定键注册观察者将通知您所有更新,无论它们来自何处。*/
指定了这一点后,可以假设通过在 的特定键上使用 KVO UserDefaults,值更改将从应用程序传播到扩展程序,反之亦然。
因此,该方法可以是在主应用程序中的每次更改时,将更改的当前时间戳保存到UserDefaults:
/// When the change is made in the main app:
let defaults = UserDefaults(suiteName: "group.<your bundle id>")
defaults["LastChangeTimestamp"] = Date()
defaults.synchronize()
Run Code Online (Sandbox Code Playgroud)
在应用扩展中:
let defaults = UserDefaults(suiteName: "group.<your bundle id>")
func subscribeForChangesObservation() {
defaults?.addObserver(self, forKeyPath: "LastChangeTimestamp", options: [.new, .initial], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// Process your changes here.
}
deinit {
defaults?.removeObserver(self, forKeyPath: "LastChangeTimestamp")
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
936 次 |
| 最近记录: |