Как исправить порядок выполнения кода в Swift 5? - PullRequest
1 голос
/ 20 сентября 2019

Код в функции выполняется в другом порядке , чем ожидается.Я хотел изменить состояние логической переменной login внутри оператора if , но функция возвращает начальное значение до , если оператор завершен .

Пример кода:

class ClassName {

    func loginRequest (name: String, pwd: String) -> Bool {

    var login:Bool
    //Initial value for login
    login = false



    let task = session.uploadTask(with: request, from: jsonData) { data, response, error in

        if let httpResponse = response as? HTTPURLResponse {
            print(httpResponse.statusCode)
            if (httpResponse.statusCode) == 200 {
                //Change the value of login if login is successful
                login = true
                if let data = data, let dataString = String(data: data, encoding: .utf8) {                    
                    do {

                        ...

                    } catch {print(error.localizedDescription)}

                }

            }

        } 

    }
        task.resume()
        //Problem return false in any case because return is completed before if statement
        return login   
    }
}

1 Ответ

2 голосов
/ 20 сентября 2019

Обработчики завершения ваш друг

В тот момент, когда ваш код запускается task.resume(), он запускает ваш uploadTask и только когда эта функция завершится, она запустит код, в котором вы измените переменную login.

При этом сказано: этот фрагмент кода выполняется асинхронно.Это означает, что ваша строка кода return login не будет ждать, пока ваш сетевой запрос вернется, прежде чем он запустится.

На самом деле ваш код работает в том порядке, в котором должен.Но я сам написал свой первый сетевой звонок, и у меня возникла та же проблема.Дескрипторы завершения - это то, как я это исправил


Вот очень хороший урок по Обработчикам завершения или вы можете знать это как Обратные вызовы:

Ссылка на учебное пособие по обработчикам завершений


Если я могу дать вам небольшой совет - вы получитенужно изменить свою функцию, чтобы она выглядела примерно так: func loginRequest (name: String, pwd: String, completionHandler: @escaping (Bool) -> Void)

И замените это login = true на completionHandler(true)

Где бы вы ни вызывали свою функцию, она будет выглядеть примерно так:

loginRequest(name: String, pwd: String) {didLogIn in
    print("Logged In : \(didLogIn)")
}

И последнее ... Вы на самом деле уже используете обработчики завершения в своем коде.let task = session.uploadTask(with: request, from: jsonData) { data, response, error in ... ... Но, надеюсь, теперь вы понимаете немного лучше и будете использовать подход обработчика завершения при выполнении сетевых вызовов.

УДАЧИ!

...