Swift URL会话和URL请求不起作用

D. *_*hen 7 urlrequest ios swift urlsession

我对这篇文章的问题非常相似,但我不完全理解答案.我已经创建了一个完成处理程序,但它似乎没有按预期工作.

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!)!)
}
Run Code Online (Sandbox Code Playgroud)

dataTask语句中的任何内容似乎都没有运行,或者至少在我尝试使用所产生的数据之前它没有完成.这个完成处理程序有什么问题?

先感谢您!

Dun*_*n C 10

您的代码结构不正确.

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()
}
Run Code Online (Sandbox Code Playgroud)

请注意,teamInput.text的强制解包非常脆弱,如果teamInput.text为nil,或者无法转换为Int,则会崩溃.编写完成处理程序以获取从teamInput.text返回的数据和int值的选项,你会好得多.

func startConnection(completion: (NSArray?, Int?) -> Void) {
Run Code Online (Sandbox Code Playgroud)

并调用它传递一个可选的:

let value: Int? = teamInput.text != nil ? Int(teamInput.text!) : nil
completion(NSArray(object: teamResult), value)
Run Code Online (Sandbox Code Playgroud)