Swift 3:URLSession / URLRequest不起作用
我仍在尝试将我们的应用程序从Swift 2转换为Swift 3,因为我*使用,因为我们所有的Apple设备现在都在运行iOS 10.
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.
我已经完成了代码转换,并认为我做得很好,但是在尝试调试我的JSON问题时(在另一个问题中发布),我现在处理的请求甚至没有被发送。
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.
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)
这意味着甚至没有提出请求。是否有一些关键我必须再次添加到PLIST?这开始变得烦人。
Which means that the request isn't even being made. Is there some key that I have to add to the PLIST again? 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!
如果在调用 getUser
后立即放置断点,则 URLSession
任务的完成处理程序,它以异步方式运行(即通常在以后完成,除非请求立即失败或被某些缓存响应满足)可能没有机会被调用。
If you put a breakpoint immediately after calling getUser
, the URLSession
task's completion handler, which runs asynchronously (i.e. generally finishes later, unless the request failed immediately or was satisfied by some cached response) may not have had a chance to be called.
如果你在 dataTask
完成处理程序,你应该在那时看到你的数据。
If you put a breakpoint inside the dataTask
completion handler, you should see your data at that point.
就个人而言,我一定要给 getUser
一个完成处理程序,以便你知道它何时完成:
Personally, I'd make sure to give getUser
a completion handler so you know when it's done:
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)
}
然后把你的断点放在 getUser
的完成处理程序。请记住,您无法保证完成处理程序将在主队列上运行,因此您需要确保将更新和UI或模型更新发送回主队列。
And just put your breakpoint in getUser
's completion handler. 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.