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()呼叫立即返回,在网络下载完成之前。

任务完成后,系统将调用您的完成处理程序(或您的代表,如果您使用代表样式)。

提防URLSess的完成处理程序和委托呼叫是在背景线程上完成的。如果您对完成任务完成任何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,则会崩溃。编写完成处理程序以获取数据和您从TeamInput返回的INT值的选项,您会更好。

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

尝试以下:

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

这对我有很多帮助

最新更新