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语句中似乎没有任何运行,或至少之前我尝试使用数据造成不完成。这个完成处理程序有什么问题?

预先感谢您!

+0

我认为,'完成(NSArray的(对象: teamResult),Int(teamInput.text!)!)''应该到你有'print(jsonResult)'的地方。现在,你开始数据任务,然后立即用(可能)'nil'调用完成处理程序。如果您在datatask处理程序中(在任何打印方法上)断点,断点是否已命中? – keithbhunter

+1

我强烈建议你看看Alamofire,如果你可以为这个项目使用它,它使得这样的代码更容易编写 –

+0

是的,将处理程序移动到数据任务似乎工作得很好。非常感谢! –

您的代码结构不正确。

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() 
} 
+0

请注意,OP的forceInwrapping的teamInput也是危险的。看到我的回答... –

试试这个:

let urlString = "www.yoururl.com" 
let url = URL(string: string.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) 

这对我帮助了很多次