我正在使用Xcode Version 9.4.1 (9F2000)

我在AppDelegate.swift中有以下代码:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    UNUserNotificationCenter.current().delegate = self
    showPushButtons()
    return true
}
func httpRequest(file: String, postKey1: String, postValue1: String, postKey2: String, postValue2: String) {
    let url = URL(string: "https://www.example.com/\(file)")!
    var request = URLRequest(url: url)
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    let postString = "\(postKey1)=\(postValue1)&\(postKey2)=\(postValue2)"
    request.httpBody = postString.data(using: .utf8)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("error=\(String(describing: error))")
            return
        }
        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        }

        let responseString = String(data: data, encoding: .utf8)
        print("responseString = \(String(describing: responseString))")
    }
    task.resume()
}
func showPushButtons(){
    let replyAction = UNTextInputNotificationAction(
        identifier: "reply.action",
        title: "Reply to message",
        textInputButtonTitle: "Send",
        textInputPlaceholder: "Write some text here")

    let pushNotificationButtons = UNNotificationCategory(
        identifier: "allreply.action",
        actions: [replyAction],
        intentIdentifiers: [],
        options: [])

    UNUserNotificationCenter.current().setNotificationCategories([pushNotificationButtons])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    if  response.actionIdentifier  ==  "reply.action" {
        if let textResponse =  response as? UNTextInputNotificationResponse {
            let sendText =  textResponse.userText
            print("Received text message: \(sendText)")
            httpRequest(file: "message.php", postKey1: "message", postValue1: "Hello!", postKey2: "chat_user", postValue2: "Peter")
        }
    }
    completionHandler()
}


它能做什么:

收到推送通知并强行触摸时,将显示文本字段和键盘(如WhatsApp之类的消息应用程序所知道的)。您可以编写一些文本并提交/发送。

您可以使用以下行获取并打印该提交的消息:

print("Received text message: \(sendText)")

这没有任何问题。

但是,当尝试像这样将数据发送到我的服务器时:

httpRequest(file: "message.php", postKey1: "message", postValue1: "Hello!", postKey2: "chat_user", postValue2: "David")


它不起作用。无法访问我的服务器,并且在控制台日志中出现如下错误:


  收到短信:第一次尝试
  
  2018-07-19 08:45:00.643935 + 0200 MyApp [4307:1502538] + [CATransaction
  同步]在事务内调用
  
  2018-07-19 08:45:00.644639 + 0200 MyApp [4307:1502538] + [CATransaction
  同步]在事务内调用
  
  2018-07-19 08:45:13.091958 + 0200 MyApp [4307:1502647] TIC TCP连接
  失败[1:0x1c4169a80]:1:50 Err(50)
  
  2018-07-19 08:45:13.093089 + 0200 MyApp [4307:1502647]任务
  。 HTTP加载失败(错误
  代码:-1009 [1:50])
  
  收到短信:第二次尝试
  
  2018-07-19 08:45:13.094756 + 0200 MyApp [4307:1503029]任务
  。完成并出现错误-代码:
  -1009
  
  2018-07-19 08:45:13.096208 + 0200 MyApp [4307:1502538] + [CATransaction
  同步]在事务内调用
  
  2018-07-19 08:45:13.096580 + 0200 MyApp [4307:1502538] + [CATransaction
  同步]在事务内调用error = Optional(Error
  Domain = NSURLErrorDomain代码= -1009“ Internet连接似乎
  处于离线状态。“ UserInfo = {NSUnderlyingError = 0x1cc047320 {Error
  Domain = kCFErrorDomainCFNetwork代码= -1009“(空)”
  UserInfo = {_ kCFStreamErrorCodeKey = 50,_kCFStreamErrorDomainKey = 1}},
  NSErrorFailingURLStringKey = https://www.example.com/message.php
  NSErrorFailingURLKey = https://www.example.com/message.php
  _kCFStreamErrorDomainKey = 1,_kCFStreamErrorCodeKey = 50,NSLocalizedDescription = Internet连接似乎是
  离线。})


我的函数httpRequest()似乎可以正常工作,因为我可以像这样从didFinishLaunchingWithOptions调用它:

httpRequest(file: "message.php", postKey1: "message", postValue1: "Hello!", postKey2: "chat_user", postValue2: "David")


没有任何问题。这也意味着我的域和服务器运行正常。

但是为什么不能从我的httpRequest()函数调用我的UNUserNotificationCenter函数?

当收到推送通知时,我的应用程序当然处于后台或关闭状态。我是否需要一些特殊的代码才能使其在后台模式下工作?

最佳答案

这是我来自AppDelegate.swift的工作代码:

//  AppDelegate.swift

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?
    var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        pushAction()
        return true
    }
    func registerForPushNotifications() {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
            (granted, error) in
            print("\nPermission granted: \(granted)\n")
            self.pushAction()
            guard granted else { return }
            self.getNotificationSettings()
        }
    }
    func getNotificationSettings() {
        UNUserNotificationCenter.current().getNotificationSettings { (settings) in
            print("\nNotification settings: \(settings)\n")
            guard settings.authorizationStatus == .authorized else { return }
            DispatchQueue.main.async(execute: {
                UIApplication.shared.registerForRemoteNotifications()
            })
        }
    }
    func httpRequest(file: String, postKey1: String, postValue1: String, postKey2: String, postValue2: String) {
        let url = URL(string: "https://www.example.com/\(file)")!
        var request = URLRequest(url: url)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        let postString = "\(postKey1)=\(postValue1)&\(postKey2)=\(postValue2)"
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print("\nerror=\(String(describing: error))\n")
                return
            }
            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("\nstatusCode should be 200, but is \(httpStatus.statusCode)\n")
                print("\nresponse = \(String(describing: response))\n")
            }
            let responseString = String(data: data, encoding: .utf8)
            print("\nresponseString = \(String(describing: responseString))\n")
        }
        task.resume()
    }
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { data -> String in
            return String(format: "%02.2hhx", data)
        }
        let token = tokenParts.joined()
        print("\nDevice Token: \(token)\n")
    }
    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("\nFailed to register: \(error)\n")
    }
    func pushAction(){
        let replyAction = UNTextInputNotificationAction(
            identifier: "reply.action",
            title: "Reply to message",
            options:[],
            textInputButtonTitle: "Send",
            textInputPlaceholder: "Input/write text here")

        let pushNotificationButtons = UNNotificationCategory(
            identifier: "allreply.action",
            actions: [replyAction],
            intentIdentifiers: [],
            options: [])

        UNUserNotificationCenter.current().setNotificationCategories([pushNotificationButtons])
    }
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
//        If you don’t want to show notification when app is open, do something else here and make a return here.
//        Even if you don’t implement this delegate method, you will not see the notification on the specified controller. So, you have to implement this delegate and make sure the below line execute. i.e. completionHandler.
        completionHandler([.sound,.alert,.badge])
    }
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        if response.actionIdentifier  ==  "reply.action" {
            if let textResponse =  response as? UNTextInputNotificationResponse {
                if UIApplication.shared.applicationState != .active{
                    self.registerBackgroundTask()
                }
                let sendText =  textResponse.userText
                print("\nReceived text message: \(sendText)\n")
                DispatchQueue.global(qos: .background).async {
                    self.httpRequest(file: "message.php", postKey1: "message", postValue1: sendText, postKey2: "user", postValue2: "Peter")
                }
            }
        }
        completionHandler()
    }
    func  registerBackgroundTask() {
        backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
            self?.endBackgroundTask()
        }
        assert(backgroundTask != UIBackgroundTaskInvalid)
    }
    func endBackgroundTask() {
        print("\nBackground task ended.\n")
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = UIBackgroundTaskInvalid
    }
}


不要忘记:

–创建推送证书

–您将在控制台日志中看到设备令牌

–在您的aps有效负载中添加"category":"allreply.action",如下所示:

{
    "aps":{
        "alert":{
            "title":"Hello",
            "body":"This is a test!"
            },
            "badge":0,
            "sound":"default",
            "category":"allreply.action"
    }
}


Push Notifications中启用Background ModesCapabilities

ios -  swift ;来自UNUserNotificationCenter的HTTP请求不起作用:Internet连接似乎已脱机-LMLPHP
ios -  swift ;来自UNUserNotificationCenter的HTTP请求不起作用:Internet连接似乎已脱机-LMLPHP

非常感谢to Raza K. from Freelancer.com

关于ios - swift ;来自UNUserNotificationCenter的HTTP请求不起作用:Internet连接似乎已脱机,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51377167/

10-14 23:53