从 Today Extension 保存到 Core Data 时,只能从 Widget 访问数据 - 而不是从主应用程序
When saving to CoreData from Today Extension, Data only accesable from Widget - NOT from Main Application
我正在为 iOS 和 Swift 编写一个应用程序 3.
在我的主 iOS 应用程序中,我使用 NSFetchedResultsController 将保存的项目显示为 TableView。
可以(当然)从另一个 ViewController 添加新项目。
-> 这一切都非常棒。
所以我认为,如果我可以从 TodayWidget 中非常快速地添加一个新项目,那就太好了。
我做了什么:
创建了一个 SharedCode Framework 并将 AppGroup 添加到我的主应用程序和 Today Widget。
移动了我的CoreDataStack.swiftClass、.xcdatamodeled和我的Item+CoreDataClass.swift 和 Item+CoreDataProperties.swift 文件到我的 SharedCode 框架。
为我的 appGroupID
将 NSPersistentContainer 转入 addforSecurityApplicationGroupIdentifier
在我的 ViewController 中重写了我的 CoreData 代码以使用创建的 CoreDataStack.shared.managedContext
测试中。惊人的。我的 NSFetchedResultsController 正在工作,并且添加新项目按预期工作。好的。 -> 继续前进。
在我的 Today Widget 中,我使用一个简单的 NSFetchRequest 从 CoreData 获取最后输入的项目。完美运行!
添加了用于修改数据并将其保存到 CoreData 的按钮。在这里我也使用 CoreDataStack.shared.managedContext 和 CoreDataStack.shared.save()
自动重新加载我的数据 AND?! 太棒了。一切都很好。数据已保存,新数据显示在 Today Extension 中。此外,当我计算 NSFetchRequest 的结果时,项目的数量会增加。
现在解决我的问题:
我通过扩展程序添加的所有数据都没有显示在我的 iOS 主应用程序中。
当我从 CoreData 中获取项目时,只有那些显示我在主应用程序中创建的项目。 -.-
我不知道出了什么问题。
就像我有两个不同的 CoreDataStores。
此外,在我通过小部件添加了一个项目之后 - 小部件不会从主应用程序中获取一个项目。只有最后一个从 Widget 输入。
- 这是我的代码:
CoreDataStack.swift
public class CoreDataStack {
public static let shared = CoreDataStack()
public var errorHandler: (Error) -> Void = {_ in }
//#1
lazy var persistentContainer: PersistentContainer = {
let container = PersistentContainer(name: ServiceConsts.modelName)
var persistentStoreDescriptions: NSPersistentStoreDescription
let storeUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID)!.appendingPathComponent("\(ServiceConsts.modelName).sqlite")
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
description.url = storeUrl
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID)!.appendingPathComponent("\(ServiceConsts.modelName).sqlite"))]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
//#2
public lazy var managedContext: NSManagedObjectContext = {
return self.persistentContainer.viewContext
}()
//#3
// Optional
public lazy var backgroundContext: NSManagedObjectContext = {
return self.persistentContainer.newBackgroundContext()
}()
//#4
public func performForegroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
self.managedContext.perform {
block(self.managedContext)
}
}
//#5
public func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
self.persistentContainer.performBackgroundTask(block)
}
//#6
public func saveContext () {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
}
PersistentContainer.swift
class PersistentContainer: NSPersistentContainer {
internal override class func defaultDirectoryURL() -> URL {
var url = super.defaultDirectoryURL()
if let newURL =
FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID) {
url = newURL
}
return url
}
}
有人可以帮忙吗?
我真的不知道我做错了什么。
如果有人能给我提示,那就太棒了:)
谢谢 <3
我终于解决了我的问题 <3。
原来如此简单。
经过数小时的测试测试哭泣并砍掉我的 MacBook ;) 我发现了让我丧命的东西。
我测试了主应用程序中的简单获取请求是否会从 Today Extension 中获取添加的项目。那是有效的。
而且比我看到的还要多。在我的主应用程序中。
NSFetchedResultController。我使用了 缓存 。
现在,当通过小部件添加新权重时,我会通知主应用程序 - 然后调用我的刷新函数。
func handleRefresh(_ refreshControl: UIRefreshControl) {
NSFetchedResultsController<NSFetchRequestResult>.deleteCache(withName: "weightCache")
do {
try fetchedResultsController.performFetch()
setupView()
self.tableView.reloadData()
} catch let error as NSError {
print("Fetching error: \(error), \(error.userInfo)")
}
refreshControl.endRefreshing()
}
就这么简单。
删除缓存即可
我正在为 iOS 和 Swift 编写一个应用程序 3.
在我的主 iOS 应用程序中,我使用 NSFetchedResultsController 将保存的项目显示为 TableView。 可以(当然)从另一个 ViewController 添加新项目。 -> 这一切都非常棒。
所以我认为,如果我可以从 TodayWidget 中非常快速地添加一个新项目,那就太好了。
我做了什么:
创建了一个 SharedCode Framework 并将 AppGroup 添加到我的主应用程序和 Today Widget。
移动了我的CoreDataStack.swiftClass、.xcdatamodeled和我的Item+CoreDataClass.swift 和 Item+CoreDataProperties.swift 文件到我的 SharedCode 框架。
为我的 appGroupID
将 NSPersistentContainer 转入 addforSecurityApplicationGroupIdentifier
在我的 ViewController 中重写了我的 CoreData 代码以使用创建的 CoreDataStack.shared.managedContext
测试中。惊人的。我的 NSFetchedResultsController 正在工作,并且添加新项目按预期工作。好的。 -> 继续前进。
在我的 Today Widget 中,我使用一个简单的 NSFetchRequest 从 CoreData 获取最后输入的项目。完美运行!
添加了用于修改数据并将其保存到 CoreData 的按钮。在这里我也使用 CoreDataStack.shared.managedContext 和 CoreDataStack.shared.save()
自动重新加载我的数据 AND?! 太棒了。一切都很好。数据已保存,新数据显示在 Today Extension 中。此外,当我计算 NSFetchRequest 的结果时,项目的数量会增加。
现在解决我的问题:
我通过扩展程序添加的所有数据都没有显示在我的 iOS 主应用程序中。 当我从 CoreData 中获取项目时,只有那些显示我在主应用程序中创建的项目。 -.-
我不知道出了什么问题。 就像我有两个不同的 CoreDataStores。 此外,在我通过小部件添加了一个项目之后 - 小部件不会从主应用程序中获取一个项目。只有最后一个从 Widget 输入。
- 这是我的代码:
CoreDataStack.swift
public class CoreDataStack {
public static let shared = CoreDataStack()
public var errorHandler: (Error) -> Void = {_ in }
//#1
lazy var persistentContainer: PersistentContainer = {
let container = PersistentContainer(name: ServiceConsts.modelName)
var persistentStoreDescriptions: NSPersistentStoreDescription
let storeUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID)!.appendingPathComponent("\(ServiceConsts.modelName).sqlite")
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
description.url = storeUrl
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID)!.appendingPathComponent("\(ServiceConsts.modelName).sqlite"))]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
//#2
public lazy var managedContext: NSManagedObjectContext = {
return self.persistentContainer.viewContext
}()
//#3
// Optional
public lazy var backgroundContext: NSManagedObjectContext = {
return self.persistentContainer.newBackgroundContext()
}()
//#4
public func performForegroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
self.managedContext.perform {
block(self.managedContext)
}
}
//#5
public func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
self.persistentContainer.performBackgroundTask(block)
}
//#6
public func saveContext () {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
}
PersistentContainer.swift
class PersistentContainer: NSPersistentContainer {
internal override class func defaultDirectoryURL() -> URL {
var url = super.defaultDirectoryURL()
if let newURL =
FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: ServiceConsts.appGroupID) {
url = newURL
}
return url
}
}
有人可以帮忙吗? 我真的不知道我做错了什么。
如果有人能给我提示,那就太棒了:)
谢谢 <3
我终于解决了我的问题 <3。
原来如此简单。
经过数小时的测试测试哭泣并砍掉我的 MacBook ;) 我发现了让我丧命的东西。
我测试了主应用程序中的简单获取请求是否会从 Today Extension 中获取添加的项目。那是有效的。
而且比我看到的还要多。在我的主应用程序中。 NSFetchedResultController。我使用了 缓存 。
现在,当通过小部件添加新权重时,我会通知主应用程序 - 然后调用我的刷新函数。
func handleRefresh(_ refreshControl: UIRefreshControl) {
NSFetchedResultsController<NSFetchRequestResult>.deleteCache(withName: "weightCache")
do {
try fetchedResultsController.performFetch()
setupView()
self.tableView.reloadData()
} catch let error as NSError {
print("Fetching error: \(error), \(error.userInfo)")
}
refreshControl.endRefreshing()
}
就这么简单。
删除缓存即可