Como chamar WidgetCenter.shared.reloadAllTimelines () quando o Core Data no CloudKit muda?

Sep 20 2020

Eu tenho um aplicativo que usa Core Data com CloudKit. As alterações são sincronizadas entre os dispositivos. O alvo principal tem a capacidade de Modos de Fundo com marcada Remote notifications, a capacidade do iCloud é marcada com os Serviços configurados para CloudKit e o contêiner correto em Contêineres marcado.

Como posso reagir no código a alterações, exclusão e adição de registros? Preciso ligar WidgetCenter.shared.reloadAllTimelines()quando o Core Data no CloudKit muda para atualizar o widget da tela inicial do iOS 14.

Meu objetivo é fazer com que isso funcione: eu altero / adiciono / apago o registro em icloud.developer.apple.com ou outro dispositivo e WidgetCenter.shared.reloadAllTimelines()chamo para exibir os dados corretos no widget. O aplicativo pode estar em segundo ou primeiro plano.

De AppDelegate.swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Register for Remote Notifications
    application.registerForRemoteNotifications()
    
    return true
}

Além disso, mensagens observadas no log de saída:

CoreData: debug: CoreData + CloudKit: - [NSCloudKitMirroringDelegate remoteStoreDidChange:] _ block_invoke (2138): <NSCloudKitMirroringDelegate: 0x281818d00> - Ignorando a notificação de alteração remota porque o exportador já detectou esta transação: 0x100b0 / 64 - <NSSQ9440> URL: file: ///var/mobile/Containers/Data/Application/F83C68DA-7C36-42CC-926D-7C721C679579/Library/Application%20Support/AppTitle.sqlite)

Respostas

5 pawello2222 Sep 19 2020 at 23:47

Se você quiser se inscrever para receber notificações remotas do Core Data, pode usar onReceive:

struct WidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text(entry.date, style: .time)
            .onReceive(NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange)) { _ in
                // make sure you don't call this too often
                WidgetCenter.shared.reloadAllTimelines()
            }
    }
}

Apenas certifique-se de não ligar com reloadAllTimelines()muita frequência - provavelmente há um número limitado de atualizações disponíveis para o seu widget.