Swift URL会话和URL请求不起作用
我遇到了非常类似的问题this post,但我不完全明白答案。我创建了一个完成处理程序,但它似乎没有按预期工作。Swift URL会话和URL请求不起作用
func updateTeam(teamID: Int) {
startConnection {NSArray, Int in
//Do things with NSArray
}
}
func startConnection(completion: (NSArray, Int) -> Void) {
let url = URL(string: "http://www.example.com/path")
var request : URLRequest = URLRequest(url: url!)
request.httpMethod = "POST"
let postString = "a=\(Int(teamInput.text!)!)"
request.httpBody = postString.data(using: .utf8)
let dataTask = URLSession.shared.dataTask(with: request) {
data,response,error in
print("anything")
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
self.teamResult = jsonResult
print(jsonResult)
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
dataTask.resume()
completion(NSArray(object: teamResult), Int(teamInput.text!)!)
}
的dataTask语句中似乎没有任何运行,或至少之前我尝试使用数据造成不完成。这个完成处理程序有什么问题?
预先感谢您!
您的代码结构不正确。
URLSession
创建异步运行的任务。您设置了一个任务,并传递一个完成块,或设置一个委托。
在网络下载完成之前,task.resume()调用立即返回。
任务完成后,系统会调用完成处理程序(或您的代理,如果使用委托样式)。
请注意URLSessions的完成处理程序和委托调用是在后台线程上完成的。如果您在完成任务时做了任何UIKit调用,则需要在主线程上完成。
@keithbhunter在他的评论中说,你需要把你的完成处理程序调用到你的任务的完成处理程序中。如果你换行完成整个处理程序调用的调用主线程这可能是最安全的:
func startConnection(completion: (NSArray, Int) -> Void) {
let url = URL(string: "http://www.example.com/path")
var request : URLRequest = URLRequest(url: url!)
request.httpMethod = "POST"
let postString = "a=\(Int(teamInput.text!)!)"
request.httpBody = postString.data(using: .utf8)
let dataTask = URLSession.shared.dataTask(with: request) {
data,response,error in
print("anything")
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
self.teamResult = jsonResult
print(jsonResult)
//Use GCD to invoke the completion handler on the main thread
DispatchQueue.main.async() {
completion(NSArray(object: teamResult), Int(teamInput.text!)!)
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
dataTask.resume()
}
注意teamInput.text你的力去包裹是非常脆弱的,而且会崩溃,如果teamInput.text是零,或者它不能转换为Int。你会好得多写你完成处理程序采取自选的数据和int值从teamInput.text回来两个:
func startConnection(completion: (NSArray?, Int?) -> Void) {
,并把它传递一个可选的:
let value: Int? = teamInput.text != nil ? Int(teamInput.text!) : nil
completion(NSArray(object: teamResult), value)
我想你也应该处理关闭时的错误。
func updateTeam(teamID: Int) {
startConnection {array, teamId, error in
// Do things with NSArray or handle error
}
}
func startConnection(completion: @escaping (NSArray?, Int, Error?) -> Void) {
let url = URL(string: "http://www.example.com/path")
var request : URLRequest = URLRequest(url: url!)
request.httpMethod = "POST"
let postString = "a=\(Int(teamInput.text!)!)"
request.httpBody = postString.data(using: .utf8)
let dataTask = URLSession.shared.dataTask(with: request) {
data,response,error in
print("anything")
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
self.teamResult = jsonResult
print(jsonResult)
DispatchQueue.main.async() {
completion(NSArray(object: self.teamResult), Int(teamInput.text!)!, nil)
}
} catch let error as NSError {
print(error.localizedDescription)
DispatchQueue.main.async() {
completion(nil, Int(teamInput.text!)!, error)
}
}
}
dataTask.resume()
}
请注意,OP的forceInwrapping的teamInput也是危险的。看到我的回答... –
试试这个:
let urlString = "www.yoururl.com"
let url = URL(string: string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
这对我帮助了很多次
我认为,'完成(NSArray的(对象: teamResult),Int(teamInput.text!)!)''应该到你有'print(jsonResult)'的地方。现在,你开始数据任务,然后立即用(可能)'nil'调用完成处理程序。如果您在datatask处理程序中(在任何打印方法上)断点,断点是否已命中? – keithbhunter
我强烈建议你看看Alamofire,如果你可以为这个项目使用它,它使得这样的代码更容易编写 –
是的,将处理程序移动到数据任务似乎工作得很好。非常感谢! –