【发布时间】:2020-03-28 09:59:21
【问题描述】:
我每 30 分钟发送一次静默推送通知,我想在静默通知到达设备时执行代码。但经过多次尝试,我无法得到结果。当我在我的设备上测试它(使用 Xcode 的版本)时,一切正常,在将其上传到 TestFlight 并从 TestFlight 下载版本后,我无法从后台唤醒应用程序或将其从终止状态唤醒。只需在启动应用程序或应用程序进入前台后执行此代码。
根据Apple documentation,我应该能够唤醒应用程序并执行 30 秒的代码。 我确认已成功发送无提示通知。我遗漏了什么?
AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
guard (userInfo["aps"] as? [String?: Any]) != nil else {
Analytics.logEvent("fetch_failed", parameters: nil)
completionHandler(.failed)
return
}
let login = UserDefaults.standard.value(forKey: "username") as? String
let password = UserDefaults.standard.value(forKey: "password") as? String
if login != nil && password != nil {
let session = URLSession.shared
let url = URL(string: "https://example.com")!
let body_values = Data(("credentials...").utf8)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", forHTTPHeaderField: "User-Agent")
request.httpBody = body_values
let loadDataTask = session.dataTask(with: request) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
if httpResponse.statusCode == 200 {
if let data = data, let dataString = String(data: data, encoding: .utf8) {
let htmlparser: HTMLParser = HTMLParser()
let numberOfEmails = htmlparser.getXPathvalue(xPath: "/html/body/div[1]/div[3]/div[3]/a[1]", fromHtml: dataString)
self.setNotification(title: "New emails!", body: "Count of new emails: \(numberOfEmails)")
completionHandler(.newData)
}
else {
completionHandler(.failed)
}
}
else {
completionHandler(.failed)
}
}
else {
completionHandler(.failed)
}
}
loadDataTask.resume()
}
else {
completionHandler(.failed)
}
}
PushNotification.js
var message = {
notification: {
},
apns: {
headers: {
'apns-priority' : '5',
'apns-push-type' : 'background'
},
payload: {
aps: {
'content-available' : 1
}
}
},
topic: topic
};
【问题讨论】:
-
除了 Caio 的观察之外,您的完成处理程序逻辑不正确。假设网络请求成功:您将使用
.newData、.noData和.failed调用完成处理程序三次!其次,如果网络请求由于某种原因失败,您根本不会调用完成处理程序。第三,如果登录名或密码为 nil,您也不会调用完成处理程序。最重要的是,确保每条执行路径都精确地调用一次完成处理程序。 -
在测试这类东西时,我喜欢unified logging,因此我可以从我的 macOS 控制台查看来自我的 iOS 应用程序的日志消息,而无需通过 Xcode 调试器运行它,这可以改变应用程序的生命周期。有关演示,请参阅 Unified Logging and Activity Tracing 视频。
-
如果您原谅不相关的观察: 1. 确保在您的 URL 中包含“https://”方案。 2. 对于未编码的请求添加密码,我会很谨慎。如果它有一个像
&这样的保留字符呢?我建议 percent-encoding 使用您的x-www-form-urlencoded请求中的值。 -
嗨@Rob,感谢您的评论。我在这里更新了代码,你可以看看。但是,即使我到处都有完成处理程序,启用了后台获取和远程通知,我也只能在我的 Xcode 版本的设备上执行静默推送,Testflight 版本不起作用......我完全迷失了。
标签: ios swift push-notification background silentpush