我正在为我订阅的每个活动收到最多四个推送通知。我已经浏览了与我的CloudKit订阅和通知注册表相关的所有内容,我确信这是一个Apple问题。相反,无论我收到多少通知,我都会将注意力转向正确处理通知。这是我正在做的简化版本:
func recievePrivatePush(_ pushInfo: [String:NSObject], completion: @escaping ()->Void) {
let notification = CKNotification(fromRemoteNotificationDictionary: pushInfo)
let alertBody = notification.alertBody
if let queryNotification = notification as? CKQueryNotification {
let recordID = queryNotification.recordID
guard let body = queryNotification.alertBody else {
return
}
if recordID != nil {
switch body {
case "Notification Type":
let id = queryNotification.recordID
switch queryNotification.queryNotificationReason {
case .recordCreated:
DataCoordinatorInterface.sharedInstance.fetchDataItem(id!.recordName, completion: {
//
})
break
default:
break
}
}
}
}
}
提取代码如下所示:
func fetchDataItem(_ id: String, completion: @escaping ()-> Void) {
if entityExistsInCoreData(id) {return}
let db = CKContainer.default().privateCloudDatabase
let recordID = CKRecordID(recordName: id)
db.fetch(withRecordID: recordID) { (record, error) in
if let topic = record {
//Here I create and save the object to core data.
}
completion()
}
}
我的所有代码都有效,我遇到的问题是,当我收到多个通知时,会在创建第一个核心数据实体之前启动多个提取请求,从而产生冗余的核心数据对象。
我想要做的是找到一种方法将获取请求添加到串行队列,以便一次处理一个。我可以将请求调用放在串行队列中,但回调总是异步运行,因此在第一个数据对象持久化之前仍会生成多个获取请求。
我尝试使用信号量和调度组,其模式如下所示:
let semaphore = DispatchSemaphore(value: 1)
func recievePrivatePush(_ pushInfo: [String:NSObject], completion: @escaping ()->Void) {
_ = semaphore.wait(timeout: .distantFuture)
let notification = CKNotification(fromRemoteNotificationDictionary: pushInfo)
let alertBody = notification.alertBody
if let queryNotification = notification as? CKQueryNotification {
let recordID = queryNotification.recordID
guard let body = queryNotification.alertBody else {
return
}
if recordID != nil {
switch body {
case "Notification Type":
let id = queryNotification.recordID
switch queryNotification.queryNotificationReason {
case .recordCreated:
DataCoordinatorInterface.sharedInstance.fetchDataItem(id!.recordName, completion: {
semaphore.signal()
})
break
default:
break
}
}
}
}
}
第二次调用上述函数并调用semaphore.wait后,第一个网络请求的执行暂停,导致应用程序冻结。
同样,我想要实现的目的是将异步网络请求添加到队列中,以便一次只创建一个,即第一个网络调用在第二个请求启动之前完成。
答案 0 :(得分:0)
卡尔,
也许你会找到你的解决方案,包括调度组,一些关键的表达方式。
let group = DispatchGroup()
group.enter()
...代码......
group.leave
group.wait()
我用它们来限制我批量发送的http请求的数量,等待响应。也许您可以将它们与我的评论中的建议一起使用。观看此视频,在这里发送群组,我想更多。
https://developer.apple.com/videos/play/wwdc2016/720/
答案 1 :(得分:0)
这些简单的课程帮助我解决了这个问题。
class PushQueue {
internal var pushArray: Array<String> = [String]()
internal let pushQueue = DispatchQueue(label: "com.example.pushNotifications")
public func addPush(_ push: Push) {
pushQueue.sync {
if pushArray.contains(push.id) {
return
} else {
pushArray.append(push.id)
processNotification(push: push)
}
}
}
internal func processNotification(push: Push) {
PushInterface.sharedInstance.recievePrivatePush(push.userInfo as! [String: NSObject])
}
}
class CKPush: Equatable {
init(userInfo: [AnyHashable: Any]) {
let ck = userInfo["ck"] as? NSDictionary
let id = ck?["nid"] as? String
self.id = id!
self.userInfo = userInfo
}
var id: String
var userInfo: [AnyHashable:Any]
public static func ==(lhs: CKPush, rhs: CKPush) -> Bool {
return lhs.id == rhs.id ? true : false
}
}
请忽略松散的力量展开。他们需要清理。