有一周我一直试图从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请求中获取值。
答案 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
中任何异步收集的材料。在收集信息之前,返回单元格。这就是异步意味着什么。你可以通过堆积更多的异步性来解决这个问题。你必须改变你的整个战略。