Swift - iOS10 - CoreData - FetchRequest в виджете Today всегда возвращает 0 элементов

Я пытаюсь использовать CoreData в своем основном приложении, и я хочу получить к нему доступ через расширение сегодня, а затем в моем приложении WatchApp.

Я добавил новую цель для своего виджета сегодня - затем активировал группы приложений для обеих целей. Конечно же, appGroup.

Затем я построил фреймворк "SharedCode". Чтобы поделиться вспомогательными классами и моим классом CoreDataStack в обоих приложениях Main и Today.

Я создал CoreDataStack, упомянутый в этом посте блога: https://swifting.io/blog/2016/09/25/25-core-data-in-ios10-nspersistentcontainer/

Также я добавил этот код, чтобы изменить каталог:

final class PersistentContainer: NSPersistentContainer {
    internal override class func defaultDirectoryURL() -> URL {
        var url = super.defaultDirectoryURL()
        if let newURL =
            FileManager.default.containerURL(
                forSecurityApplicationGroupIdentifier: CoreDataServiceConsts.applicationGroupIdentifier) {
            url = newURL
        }
        return url
    }
}

Это мой класс CoreDataStack Helper:

struct CoreDataServiceConsts {
    static let applicationGroupIdentifier = "nnnnnnnnn.group.is.xnd.xyz"
    static let modelName = "Weight"
}

public class CoreDataStack {

    public static let shared = CoreDataStack()
    public var errorHandler: (Error) -> Void = {_ in }

    //#1
    public lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: CoreDataServiceConsts.modelName)
        container.loadPersistentStores(completionHandler: { [weak self](storeDescription, error) in
            if let error = error {
                NSLog("CoreData error \(error), \(error._userInfo)")
                self?.errorHandler(error)
            }
        })
        return container
    }()

    //#2
    public lazy var viewContext: 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.viewContext.perform {
            block(self.viewContext)
        }
    }

    //#5
    public func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
        self.persistentContainer.performBackgroundTask(block)
    }

    public func saveContext () {
        guard viewContext.hasChanges else { return }

        do {
            try viewContext.save()
        } catch let error as NSError {
            print("Unresolved error \(error), \(error.userInfo)")
        }
    }
}

И я построил подкласс для NSPersistentContainer:

final class PersistentContainer: NSPersistentContainer {

    internal override class func defaultDirectoryURL() -> URL {
        var url = super.defaultDirectoryURL()

        if let newURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: CoreDataServiceConsts.applicationGroupIdentifier) {
            url = newURL
        }

        return url
    }
}

В моем основном приложении я использую NSFetchedResultController - добавление и получение сущностей работает отлично:)

Теперь я хочу читать из CoreData - я использую FetchRequest:

func fetchWeights() {

    let fetchRequest: NSFetchRequest<Measure> = Measure.fetchRequest()
    let dateSort = NSSortDescriptor(key: #keyPath(Measure.date), ascending: false)
    fetchRequest.sortDescriptors = [dateSort]
    fetchRequest.returnsObjectsAsFaults = false

    do {
        let results = try CoreDataStack.shared.viewContext.fetch(fetchRequest)
        if results.count > 0 {
            // There are found Weigts
            print("weights FOUND: \(results.count)")
        } else {
            // Nil Weights found
            print("NO weights: \(results.count)")
        }
    } catch let error as NSError {
        print("Fetch error: \(error) description: \(error.userInfo)")
    }
}

Нет запроса на выборку всегда возвращает ноль объектов. Но в моем CoreData есть объекты, которые отображаются в моем основном приложении.

Есть идеи? Я понятия не имею, что я делаю не так. Спасибо за вашу помощь.

1 ответ

Решение

Вы определили PersistentContainer подкласс переопределить defaultDirectoryURL, но твой CoreDataStack все еще использует сборку в NSPersistentContainer введите для вашего ленивого контейнера.

Это должно сделать трюк:

public class CoreDataStack {

public static let shared = CoreDataStack()
public var errorHandler: (Error) -> Void = {_ in }

//#1
public lazy var persistentContainer: PersistentContainer = {
    let container = PersistentContainer(name: CoreDataServiceConsts.modelName)
    container.loadPersistentStores(completionHandler: { [weak self](storeDescription, error) in
        if let error = error {
            NSLog("CoreData error \(error), \(error._userInfo)")
            self?.errorHandler(error)
        }
    })
    return container
}()

Приветствия Михал

Другие вопросы по тегам