无法从dataTask()返回数据

时间:2018-06-09 15:19:43

标签: swift closures httprequest completionhandler

有一周我一直试图从dataTask()返回一个字符串。

我已经在StackOverFlow上阅读了很多内容,也从他们处理此主题的serval网站上阅读了很多内容。例如,this one。所以我已经明白,dataTask不会直接返回值,导致它发生在不同的线程上,依此类推。我还读到了关闭和完成处理程序。我真的觉得我实际上已经知道这是什么了解。但我无法让它发挥作用。

所以这是我的代码。我只是发布了整个代码,所以没有人需要担心问题会出现在我没有展示的部分。一切正常,直到我尝试返回一个值并将其保存在例如变量中:

func requestOGD(code gtin: String, completion: @escaping (_ result: String) -> String) {
    // MARK: Properties
    var answerList: [String.SubSequence] = []
    var answerDic: [String:String] = [:]
    var product_name = String()
    var producer = String()

    // Set up the URL request
    let ogdAPI = String("http://opengtindb.org/?ean=\(gtin)&cmd=query&queryid=400000000")

    guard let url = URL(string: ogdAPI) else {
        print("Error: cannot create URL")
        return
    }

    let urlRequest = URLRequest(url: url)
    // set up the session
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    // make the request
    let task = session.dataTask(with: urlRequest) {
        (data, response, error) in
        // check for any errors
        guard error == nil else {
            print("error calling GET on /todos/1")
            print(error!)
            return
        }
        // make sure we got data
        guard let responseData = data else {
            print("Error: did not receive data")
            return
        }

        // parse the result, which is String. It willbecome split and placed in a dictionary
        do {
            let answer = (String(decoding: responseData, as: UTF8.self))

            answerList = answer.split(separator: "\n")

            for entry in answerList {
                let entry1 = entry.split(separator: "=")
                if entry1.count > 1 {
                    let foo = String(entry1[0])
                    let bar = String(entry1[1])
                    answerDic[foo] = "\(bar)"
                }
            }

            if answerDic["error"] == "0" {
                product_name = answerDic["detailname"]!
                producer = answerDic["vendor"]!

                completion(product_name)
            } else {
                print("Error-Code der Seite lautet: \(String(describing: answerDic["error"]))")
                return
            }
        }
    }
    task.resume()

这里我调用了我的函数,并没有后顾之忧,我也尝试直接将它返回到var foo,也不起作用该值只存在于闭包内:

    // Configure the cell...
    var foo:String = ""

    requestOGD(code: listOfCodes[indexPath.row]) { (result: String) in
        print(result)
        foo = result
        return result
    }

    print("Foo:", foo)

    cell.textLabel?.text = self.listOfCodes[indexPath.row] + ""

    return cell
}

所以我的问题是,我感觉我无法从http请求中获取值。

1 个答案:

答案 0 :(得分:1)

您在致电requestOGD时使用了完成处理程序:

requestOGD(code: listOfCodes[indexPath.row]) {
    (result: String) in
    // result comes back here
}

但是你试图捕获并返回结果

    foo = result
    return result

所以你在这里犯了同样的错误,你试图通过首先拥有完成处理程序来避免犯错。对完成处理程序的调用本身是异步的。所以你再次面临同样的问题 。如果您想在此时提取result,则需要另一个完成处理程序。

简单来说,这就是操作的顺序:

requestOGD(code: listOfCodes[indexPath.row]) {
    (result: String) in
    foo = result // 2
}
print("Foo:", foo) // 1

您在异步代码运行之前打印foo,并且有可能首先设置foo

在更大的上下文中:无法使用cellForRowAt中任何异步收集的材料。在收集信息之前,返回单元格。这就是异步意味着什么。你可以通过堆积更多的异步性来解决这个问题。你必须改变你的整个战略。