I've continued to troubleshoot this issue over the last week and change.
My subscription does not register (cannot see it on production Subscriptions page on Cloudkit Console) and my fetch data (add(CKDatabaseOperation) returns no data.
Neither operation returns any error messages. It's like the query finds no matches, but I've reviewed everything repeatedly and the field names are correct. All fields are indexed.
I've verified the Security Roles. The whole thing works flawlessly on the simulator for development and production schemas, but does nothing with testing on a real device from Xcode or TestFlight.
Here is the source for my custom app delegate for my subscription
| import SwiftUI |
| import UserNotifications |
| import CloudKit |
| |
| class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject, UNUserNotificationCenterDelegate { |
| @Published var isNotificationPresent: Bool = false |
| @Published var notificationTapped: Bool = false |
| |
| var app: iLS_ToolkitApp? |
| |
| func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { |
| |
| if getIcloudStatus() { |
| |
| UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { authorized, error in |
| if authorized { |
| DispatchQueue.main.async(execute: { |
| application.registerForRemoteNotifications() |
| }) |
| } |
| else { |
| print("Request Error: \(error?.localizedDescription ?? "Not Returned")") |
| } |
| }) |
| UNUserNotificationCenter.current().delegate = self |
| } else { |
| print("AppDeleagte iCloud not avaliable") |
| } |
| |
| return true |
| } |
| |
| func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { |
| |
| let stringToken = deviceToken.map { String(format: "%02.2hhx", $0)}.joined() |
| print("Device Token: \(stringToken)") |
| |
| let subscription = CKQuerySubscription(recordType: "news", predicate: NSPredicate(value: true), subscriptionID: "news_feed", options: .firesOnRecordCreation) |
| |
| let notification = CKSubscription.NotificationInfo() |
| notification.titleLocalizationKey = "%1$@" |
| notification.titleLocalizationArgs = ["title"] |
| notification.alertLocalizationKey = "%1$@" |
| notification.alertLocalizationArgs = ["message"] |
| notification.soundName = "default" |
| notification.shouldSendContentAvailable = true |
| |
| subscription.notificationInfo = notification |
| |
| CKContainer.default().publicCloudDatabase.save(subscription) { _, error in |
| if let error { |
| print("Subscription Error: \(error)") |
| } |
| } |
| } |
| |
| func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError: Error) { |
| print("Registration Failure \(Error.self)") |
| } |
| } |
| |
| extension AppDelegate { |
| |
| |
| func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { |
| print("Notification Recieved") |
| notificationTapped = true |
| } |
| |
| |
| func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions { |
| isNotificationPresent = true |
| return [.banner, .list, .badge, .sound] |
| } |
| |
| func getIcloudStatus() -> Bool { |
| CKContainer.default().accountStatus { returnedStatus, returnedError in |
| DispatchQueue.main.async { |
| switch returnedStatus { |
| case .available: |
| print("AppDelegate Cloudkit is available") |
| default : |
| print("AppDelegate Cloudkit is not available") |
| return |
| } |
| } |
| } |
| return true |
| } |
| } |
| |
The source for my class to read the messages will be in the next reply