CKQueryNotification соединение с SwiftUI - PullRequest
0 голосов
/ 16 апреля 2020

Я пытаюсь получить фоновые уведомления о подписке из базы данных CloudKit publi c самым простым способом. У меня возникли проблемы, что именно должно быть внутри функции, которая обрабатывает пожары подписки и добавляет их в тип коллекции, будь то в didReceiveRemoteNotification или где-то еще. Список @State должен отражать список записей базы данных, но я не уверен, как мне это сделать. Я пробовал с @EnvironmentObject и некоторыми другими способами, но к нему ничего не добавлялось. В приведенном ниже коде, когда я добавляю новую запись, я получаю только: ЕСТЬ НИЧЕГО ПЕРЕД: [] ЕСТЬ НИЧЕГО ПОСЛЕ: [] Это не значит, что я не получаю объект записи, хотя. Я понимаю, но список остается []. Сейчас я в основном заинтересован в fetchRecord (), который предназначен для вновь создаваемых записей.

Я хочу, чтобы list автоматически добавлял новейшую title и отображал ее на экране каждый раз, когда я создаю новую запись с панели инструментов CloudKit или где-то еще.

Наконец, это тихие уведомления, а не pu sh. Спасибо и будьте в безопасности!

ContentView

import SwiftUI
import CloudKit



struct ContentView: View {
    let publicData = CKContainer.default().publicCloudDatabase

    @State var list: [String] = []

    func fetchData() {

        let query = CKQuery(recordType: "OLALA", predicate: NSPredicate(value: true))

        self.publicData.perform(query, inZoneWith: nil, completionHandler: { (records, error) in

        guard let records = records else { return }

            DispatchQueue.main.async {
                for record in records {
                    if let title = record.object(forKey: "title") as? String {
                        self.list.append(title)

                    }
                }
            }
        })
    }

    func subscribe() {

        let subscription = CKQuerySubscription(recordType: "OLALA", predicate: NSPredicate(value: true), options: [.firesOnRecordDeletion, .firesOnRecordUpdate, .firesOnRecordCreation])
        let info = CKSubscription.NotificationInfo()
        info.shouldSendContentAvailable = true
        subscription.notificationInfo = info


        self.publicData.save(subscription) { (savedSubscription, error) in
            if error != nil {
                print(error!.localizedDescription)
            } else {
                print("Subscribed!")
            }
        }
    }

    func deleteSubscriptions() {
        publicData.fetchAllSubscriptions { subscriptions, error in
            if error == nil {
                if let subscriptions = subscriptions {
                    for subscription in subscriptions {
                        self.publicData.delete(withSubscriptionID: subscription.subscriptionID) { str, error in
                            if error != nil {
                                print(error!.localizedDescription)
                            }
                        }
                    }


                }
            } else {

                print(error!.localizedDescription)
            }
        }
    }

    func fetchRecord(record: CKRecord.ID) {

        self.publicData.fetch(withRecordID: record) { (record, error) in
            if error != nil {
                print(error!.localizedDescription)
            } else {

                DispatchQueue.main.async {
                    if let title = record?.object(forKey: "title") as? String {
                        print("IS THERE ANYTHING BEFORE: \(self.list)")
                        self.list.append(title)
                        print("IS THERE ANYTHING AFTER: \(self.list)")

                    }
                }

            }
        }
    }
    func deleteRecord(record: CKRecord.ID) {

        self.publicData.fetch(withRecordID: record) { (record, error) in
            if error != nil {
                print(error!.localizedDescription)
            } else {
                DispatchQueue.main.async {
                    if let title = record?.object(forKey: "title") as? String {
                        if let index = self.list.firstIndex(of: title) {
                            self.list.remove(at: index)
                        }
                    }
                }

            }
        }
    }

    var body: some View {
        VStack {
            HStack {
                Button(action: {
                    self.fetchData()
                }, label: {
                    Text("Fetch")
                })
                Spacer()
                Button(action: {
                    self.list.removeAll()
                }, label: {
                   Text("Clear")
                })
                Spacer()
                Button(action: {
                    self.subscribe()
                }, label: {
                    Text("Subscribe")
                })
                Spacer()
                Button(action: {
                    self.deleteSubscriptions()
                }, label: {
                    Text("Delete subs")
                })
            }.padding(.vertical, 40)
            .padding(.horizontal, 20)
            List(self.list, id: \.self) { title in
                Text(title)
            }
        }
    }
}

AppDelegate:

import UIKit
import CoreData
import CloudKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {


    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("\n\nTOKEN TAKEN\n\n")
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        //let dict = userInfo as! [String : NSObject]
        let notification = CKQueryNotification(fromRemoteNotificationDictionary: userInfo)

        if notification?.queryNotificationReason == .recordCreated {
            ContentView().fetchRecord(record: (notification?.recordID)!)
        }
        if notification?.queryNotificationReason == .recordUpdated {
            //later
        }
        if notification?.queryNotificationReason == .recordDeleted {
            ContentView().deleteRecord(record: (notification?.recordID)!)
        }


    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        UIApplication.shared.registerForRemoteNotifications()

        return true
    }
...
}
...