从Today Extension中保存到CoreData时,只能从Widget访问数据 - 不能从主应用程序

时间:2017-01-28 00:35:51

标签: swift core-data swift3 today-extension ios10-today-widget

我正在使用Swift 3编写iOS应用程序。

在我的主iOS应用程序中,我使用NSFetchedResultsController将已保存的项目显示为TableView。 它(当然)可以从另一个ViewController添加新项目。 - >这一切都非常棒。

所以我认为如果能够从TodayWidget中快速添加新项目会很棒。

我做了什么:

  1. 创建了一个SharedCode框架,并将AppGroup添加到我的主应用程序和今日小部件中。

  2. 移动了我的 CoreDataStack.swift 类, .xcdatamodeled 和我的 Item + CoreDataClass.swift Item + CoreDataProperties.swift 文件到我的SharedCode Framework。

  3. 为我的appGroupID 提供NSPersistentContainer addforSecurityApplicationGroupIdentifier

  4. 在我的ViewController中重写了我的CoreData代码,以使用创建的 CoreDataStack.shared.managedContext

  5. 测试。真棒。我的NSFetchedResultsController正在工作,添加新项目按预期工作。尼斯。 - >继续前进。

  6. 在我的今日小工具中,我使用简单的NSFetchRequest从CoreData获取最后输入的项目。完美运作!

  7. 添加了按钮来修改数据并将其保存到CoreData。在这里,我还使用 CoreDataStack.shared.managedContext CoreDataStack.shared.save()

  8. 自动重新加载我的数据 AND?! 非常棒。一切都很好。保存数据并在Today Extension中显示新数据。此外,当我计算NSFetchRequest的结果时,项目数量会增加。

  9. 现在我的问题:

    我通过扩展程序添加的所有数据都没有显示在我的主iOS应用程序中。 当我从CoreData中获取Items时,只显示我在主应用程序中创建的那些。 -.-

    我不知道哪里出错了。 就像我有两个不同的CoreDataStores。 此外,在我通过Widget添加了一个Item之后 - Widget也没有从主App中获取一个Item。只有最后一个从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

1 个答案:

答案 0 :(得分:1)

我终于解决了我的问题< 3。

这很简单。

经过数小时和数小时的测试测试哭泣并通过我的MacBook放了一把刀;)我发现了那件事让我感到害怕。

我测试主应用程序中的简单获取请求是否会从今日扩展中获取添加的项目。这很有效。

而不是我看到它。在我的主应用程序中。 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()
}

这么简单。

只需删除缓存。