简体   繁体   English

Swift 3:URLSession / URLRequest无法正常工作

[英]Swift 3: URLSession / URLRequest Not Working

I am still trying to convert our application from Swift 2 over to Swift 3 because I am being forced to since all of our Apple devices are now running iOS 10. 我仍然试图将我们的应用程序从Swift 2转换到Swift 3,因为由于我们所有的Apple设备现在都在运行iOS 10,因此我不得不这样做。

I have gone through the code conversion and thought I was doing well however, while attempting to debug my JSON issues (posted in another question), I am now dealing with requests not even being sent. 我经历了代码转换,并认为我做得不错,但是在尝试调试JSON问题(发布在另一个问题中)时,我现在正在处理甚至没有发送的请求。

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    var request = URLRequest(url: URL(string: "http://domain.tld/path/")!)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    NSLog("Got here?")

    session.dataTask(with: request) {data, response, error in
        guard let data = data, error == nil else {
            print("error=\(error)")
            return
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data)

        NSLog("Object: \(object)")
    }.resume()

    NSLog("Got here 4?")
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

The code above yields the following output: 上面的代码产生以下输出:

2016-10-04 13:00:12.011969 OneTouch[1589:623015] [DYMTLInitPlatform] platform initialization successful
2016-10-04 13:00:12.264319 OneTouch[1589:622954] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2016-10-04 13:00:12.265321 OneTouch[1589:622954] [MC] Reading from public effective user settings.
2016-10-04 13:00:12.295055 OneTouch[1589:622954] Got here?
2016-10-04 13:00:12.295445 OneTouch[1589:622954] Got here 4?
2016-10-04 13:00:12.295515 OneTouch[1589:622954] End of getUser
(lldb) 

Which means that the request isn't even being made. 这意味着甚至没有提出请求。 Is there some key that I have to add to the PLIST again? 是否有一些密钥我必须再次添加到PLIST中? This is starting to get annoying. 这开始变得烦人了。

Below is my old code and it isn't even working anymore: 以下是我的旧代码,现在甚至无法正常工作:

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    let request = NSMutableURLRequest(url: URL(string: "http://domain.tld/path/" as String)!, cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 20)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    NSLog("Got here?")

    let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {data, response, error in
        if error != nil {
            NSLog("Got here 2?")
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data!)

        NSLog("Object: \(object)")
    })

    NSLog("Got here 4?")

    task.resume()
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

The code above yields the same output as the other code does! 上面的代码产生与其他代码相同的输出!

If you put a breakpoint immediately after calling getUser , the URLSession task's completion handler, which runs asynchronously (ie generally finishes later, unless the request failed immediately or was satisfied by some cached response) may not have had a chance to be called. 如果您在调用getUser之后立即放置一个断点,则该URLSession任务的完成处理程序将异步运行(即,通常在以后完成,除非请求立即失败或被某些缓存的响应满足),否则可能没有机会被调用。

If you put a breakpoint inside the dataTask completion handler, you should see your data at that point. 如果在dataTask完成处理程序中放置一个断点,则应在该点看到数据。


Personally, I'd make sure to give getUser a completion handler so you know when it's done: 就个人而言,我将确保为getUser一个完成处理程序,以便您知道何时完成:

func getUser(completionHandler: @escaping (JSON?, Error?) -> Void) {
    let params = [
        "email":"\(preferences.string(forKey: "preference_email")!)"
    ]

    let requestParams: [String: Any] = [
        "action": "601",
        "params": params
    ]

    do {
        let requestObject = try JSONSerialization.data(withJSONObject: requestParams)

        var request = URLRequest(url: URL(string: "http://domain.tld/path/")!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20)

        request.httpBody = requestObject
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) {data, response, error in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }

            completionHandler(JSON(data: data), nil)
        }

        task.resume()
    } catch {
        completionHandler(nil, error)
    }
}

Then when you call it, you can do something like: 然后,当您调用它时,您可以执行以下操作:

getUser { json, error in
    guard let json = json else {
        print(error)
        return
    }

    // do something with json
    print(json)
}

And just put your breakpoint in getUser 's completion handler. 并将断点放在getUser的完成处理程序中。 And remember that you have no assurances that the completion handler will run on the main queue or not, so you'll want to make sure to dispatch and UI or model updates back to the main queue. 并且请记住,您无法保证完成处理程序是否会在主队列上运行,因此您需要确保将UI和模型更新分派回主队列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM