Не удается получить данные, возвращенные из dataTask () - PullRequest
0 голосов
/ 09 июня 2018

В течение одной недели я пытался получить строку, возвращаемую из dataTask ().

Я уже много читал здесь, на StackOverFlow, а также на сайтах сервалов, где они занимаются этой темой.Например, это .Итак, я уже понимаю, что 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 голосов
/ 09 июня 2018

Вы использовали обработчик завершения в своем вызове 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.Ячейка возвращается до информация собирается.Вот что означает асинхронный .Вы не можете обойти это, накапливая дальнейшие уровни асинхронности.Вы должны изменить всю свою стратегию.

...