Swift URL会话和URL请求不起作用 [英] Swift URL Session and URL Request not working

查看:224
本文介绍了Swift URL会话和URL请求不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到与此帖子非常相似的问题,但我没有无法完全理解答案.我已经创建了完成处理程序,但是它似乎没有按预期工作.

I am getting very similar problems to this post, but I don't fully understand the answer. I've created a completion handler, but it doesn't seem to be working as expected.

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语句中的任何内容似乎都没有运行,或者至少在我尝试使用结果数据之前没有完成.此完成处理程序有什么问题?

Nothing within the dataTask statement seems to run, or at least it doesn't complete before I try to use the data resulted. What is wrong with this completion handler?

提前谢谢!

推荐答案

您的代码结构不正确.

Your code is structured incorrectly.

URLSession创建异步运行的任务.您设置了任务,然后传递了完成框,或者设置了委托.

URLSession creates tasks that are run asynchronously. You set up a task, and either pass in a completion block, or set up a delegate.

task.resume()调用会在网络下载完成很久之前立即返回.

The task.resume() call returns immediately, long before the network download is complete.

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

Once the task is complete, the system calls your completion handler (or your delegate, if you use the delegate style).

请注意,URLSession的完成处理程序和委托调用是在后台线程上完成的.如果您响应任务完成而执行任何UIKit调用,则需要在主线程上进行.

Beware that URLSessions' completion handlers and delegate calls are done on a background thread. If you do any UIKit calls in response to a task completing, you need to do it on the main thread.

正如@keithbhunter在评论中所说,您需要将对完成处理程序的调用放在任务的完成处理程序内.如果将整个完成处理程序调用包装在对主线程的调用中,那可能是最安全的:

As @keithbhunter says in his comment, you need to put the call to your completion handler inside the completion handler for your task. It's probably safest if you wrap that whole completion handler call in a call to the main thread:

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为nil或无法将其转换为Int,则会崩溃.您最好编写完成处理程序,以对从teamInput.text返回的数据和int值采取可选参数:

Note that your force-unwrapping of teamInput.text is very fragile, and will crash if teamInput.text is nil, or if it can't be converted to an Int. You'd be much better off to write your completion handler to take optionals for both the data and the int value you get back from teamInput.text:

func startConnection(completion: (NSArray?, Int?) -> Void) {

并通过可选参数调用它:

and call it passing in an optional:

let value: Int? = teamInput.text != nil ? Int(teamInput.text!) : nil
completion(NSArray(object: teamResult), value)

这篇关于Swift URL会话和URL请求不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆