Swift如何从URLSession返回数据

14

我无法从我的HTTP请求中返回数据,也无法使完成处理程序正常工作。因此,请协助我解决这个问题:

public static func createRequest(qMes: message, location: String, method: String) -> String{
    let requestURL = URL(string: location)
    var request = URLRequest(url: requestURL!)

    request.httpMethod = method
    request.httpBody = qMes.toString().data(using: .utf8)

    let requestTask = URLSession.shared.dataTask(with: request) {
        (data: Data?, response: URLResponse?, error: Error?) in

        if(error != nil) {
            print("Error: \(error)")
        }

        return String(data: data!, encoding: String.Encoding.utf8) as String!
    }
    requestTask.resume()
}

在无返回值函数中期望非空返回语句。此时我一筹莫展...


1
你的return语句在dataTask(with:completionHandler:)函数的完成块内部; 你的公共函数createRequest没有返回任何内容,尽管它声称返回一个String - dirkgroten
简单地做:var webString = try String(contentsOf: URL(string: url)!) - Vadim
4个回答

33
您可以使用此完成块方法发送最终响应:
例如: 我已在完成块中返回String,在无错误的成功响应后,只需将结果传递给块。
  public func createRequest(qMes: String, location: String, method: String , completionBlock: @escaping (String) -> Void) -> Void
    {

        let requestURL = URL(string: location)
        var request = URLRequest(url: requestURL!)

        request.httpMethod = method
        request.httpBody = qMes.data(using: .utf8)

        let requestTask = URLSession.shared.dataTask(with: request) {
            (data: Data?, response: URLResponse?, error: Error?) in

            if(error != nil) {
                print("Error: \(error)")
            }else
            {

                let outputStr  = String(data: data!, encoding: String.Encoding.utf8) as String!
                //send this block to required place
                completionBlock(outputStr!);
            }
        }
        requestTask.resume()
    } 
你可以使用下面的代码来执行上述完成块函数:

您可以使用以下代码来执行上面的完成块函数:

 self.createRequest(qMes: "", location: "", method: "") { (output) in

        }
这将解决您的以下要求。

非常感谢您的详细解释。如果您想在另一个控制器中使用它,您可以创建一个共享静态对象来调用您的函数。let networkObj = NetworkController() networkObj.sharedNetwork.createRequest(attributes) { (output) in print(output) } - Dushyant Deshwal

7
{
    (data: Data?, response: URLResponse?, error: Error?) in

    if(error != nil) {
        print("Error: \(error)")
    }

    return String(data: data!, encoding: String.Encoding.utf8) as String!
}

这段代码是dataTask()方法的完成处理程序。它是一段代码块,你将其传递到dataTask()方法中以便稍后执行(当服务器发送回一些数据或出现错误时)。它不会立即执行。

这意味着当你上面的createRequest()方法正在执行时,它会直接跳过这段代码,然后进入requestTask.resume()行,然后方法结束。此时,因为你的方法被定义为返回一个String,你需要返回一个String。从完成处理程序中返回它是无效的,因为那还没有执行,它将在稍后执行。

有许多不同的处理异步编程的方式,但解决这个问题的一种方法是修改你的createRequest()方法,使其不再定义为返回一个String,创建一个以String参数作为输入,并对返回值执行所需操作的方法,然后从完成处理程序中调用该方法。


谢谢提供额外的信息,之前有些难以理解!太好了! - Bram

1

不要使用return,尝试使用你在问题中提到的完成处理程序。

func createRequest(qMes: message, location: String, method: String, completionHandler: @escaping (_ data:Data?, _ response: URLResponse?, _ error: NSError?) -> Void)

那么你应该使用类似于 completionHandler(data, response, error) 的东西,而不是 return

这是如何发起请求的:

var request = URLRequest(url: Foundation.URL(string: URL)!)
        request.httpMethod = method
        //request.addValue(authString, forHTTPHeaderField: "Authorization") // if you need some

        let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in

            guard error == nil && data != nil else
            {
                print("error=\(error)")
                completionHandler(data, response, error as NSError?)
                return
            }

            completionHandler(data, response, error as NSError?)
        }) 

        task.resume()

0

只需在您的函数调用中

var webString = try String(contentsOf: URL(string: url)!)

而且你可以将完整的字符串响应返回


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接