![](/img/trans.png)
[英]iOS 11 CloudKit Record changes notifications not received in Single App or Guided Access Mode
[英]Mark Notifications as Read in iOS 11 with CloudKit
我有一個使用CloudKit
的應用程序,並且在iOS 11
之前一切正常。
在以前的 iOS 版本中,我使用CKQuerySubscription
和NSPredicate
來在用戶更改特定表時接收通知,匹配NSPredicate
屬性。
這樣做之后,每當服務器發送通知時,我都會遍歷它們,獲取其更改,然后將它們標記為READ
以便我再次解析它們(保存serverToken
)。
現在在 iOS 11 中,Xcode 通知我這些委托已deprecated
,我應該更改它們,但這就是我遇到問題的地方 - 我無法弄清楚如何以未棄用的方式為 iOS 11 做到這一點。
這是我的代碼:
保存訂閱
fileprivate func setupCloudkitSubscription() {
let userDefaults = UserDefaults.standard
let predicate = NSPredicate(format: /*...*/) // predicate here
let subscription = CKQuerySubscription(recordType: "recordType", predicate: predicate, subscriptionID: "tablename-changes", options: [.firesOnRecordUpdate, .firesOnRecordCreation])
let notificationInfo = CKNotificationInfo()
notificationInfo.shouldSendContentAvailable = true // if true, then it will push as a silent notification
subscription.notificationInfo = notificationInfo
let publicDB = CKContainer.default().publicCloudDatabase
publicDB.save(subscription) { (subscription, err) in
if err != nil {
print("Failed to save subscription:", err ?? "")
return
}
}
}
檢查待處理的通知
fileprivate func checkForPendingNotifications() {
let serverToken = UserDefaults.standard.pushNotificationsChangeToken
let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: serverToken)
var notificationIDsToMarkRead = [CKNotificationID]()
operation.notificationChangedBlock = { (notification) -> Void in
if let notificationID = notification.notificationID {
notificationIDsToMarkRead.append(notificationID)
}
}
operation.fetchNotificationChangesCompletionBlock = {(token, err) -> Void in
if err != nil {
print("Error occured fetchNotificationChangesCompletionBlock:", err ?? "")
print("deleting existing token and refetch pending notifications")
UserDefaults.standard.pushNotificationsChangeToken = nil
return
}
let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)
markOperation.markNotificationsReadCompletionBlock = { (notificationIDsMarkedRead: [CKNotificationID]?, operationError: Error?) -> Void in
if operationError != nil {
print("ERROR MARKING NOTIFICATIONS:", operationError ?? "")
return
}
}
let operationQueue = OperationQueue()
operationQueue.addOperation(markOperation)
if token != nil {
UserDefaults.standard.pushNotificationsChangeToken = token
}
}
let operationQueue = OperationQueue()
operationQueue.addOperation(operation)
}
如您所見,上面的代碼在 iOS 11 之前都可以完美運行;
現在 Xcode 在以下幾行提示警告:
let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: serverToken)
警告:
'CKFetchNotificationChangesOperation' 在 iOS 11.0 中被棄用:不是迭代通知來枚舉更改的記錄區域,而是使用 CKDatabaseSubscription、CKFetchDatabaseChangesOperation 和 CKFetchRecordZoneChangesOperation
和
let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)
警告:
'CKMarkNotificationsReadOperation' 在 iOS 11.0 中被棄用:考慮使用 CKDatabaseSubscription、CKFetchDatabaseChangesOperation 和 CKFetchRecordZoneChangesOperation,而不是迭代通知
我試圖將CKDatabaseSubscription
但這樣做,我不能應用NSPredicate
來篩選訂閱,因為我可以用做CKQuerySubscription
,如果我嘗試獲取和馬克待定通知,如在Read
它顯示這些警告。
在這種情況下, iOS 11
的最佳方法是什么? 任何提示?
謝謝你。
因此,正如我在上面的openradar
錯誤報告中的評論中提到的,可以在這里找到這是iOS 11
一個已知問題,當獲取公共記錄的更改然后將這些更改標記為已讀,保存給定的令牌時。
由於這個問題沒有真正的解決方案,因為 Apple 沒有為此提供解決方法,或者在給出解決方案之前可能沒有將這些委托函數標記為已棄用,因此我不得不通過不同的路徑,這是以下內容:
我必須在Private Database
創建一個自定義CKRecordZone
,然后我必須訂閱該zoneID
數據庫更改,通過這樣做,每當用戶更改該數據庫中的某些內容時,所需的push-notifications
和/或silent-push-notifications
觸發預期然后我可以解析新數據。
我的問題是我在公共數據庫中有User Profile
,所以每當用戶更改與他相關的內容(姓名、簡歷等)時,它都會保存在 CloudKit 中,並且靜默通知會向用戶的其他設備觸發以更新此數據 -這我也可以用私人數據庫完美地完成 - 但我的問題是其他用戶可以搜索應用程序用戶來關注 - 取消關注他們,如果該數據存儲在私人數據庫中,它將超出一般用戶的搜索范圍.
為了克服這個問題,我不得不半復制用戶配置文件數據。 用戶通過私有數據庫獲取和編輯其數據,並在保存時更新公共數據庫中的半相關表,以便可以搜索普通用戶。
在 Apple 允許我們像以前在iOS 10
那樣從公共數據庫中獲取更改之前,此解決方案將暫時適用於我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.