@Mimuss

Почему такая долгая инициализация UILabel?

Существует простой код, который делает POST - запрос яндекса-переводчика API. Получается ответ - переведенный текст. Однако при получения ответа (и даже вывода ответа на консоль) инициализация UILabel происходит очень долго, спустя несколько секунд. Как это устранить? Почему это происходит?

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!{
        didSet{
            textField.delegate = self
            textField.text = textToTranslate
        }
    }

    @IBOutlet weak var label: UILabel!{
        didSet{
            print("didSet")
        }
    }

    var textToTranslate: String?{
        didSet{
            TranslateTheText()
        }
    }

    private func TranslateTheText(){
        var request = URLRequest(url: URL(string: "https://translate.yandex.net/api/v1.5/tr.json/translate")!)
        request.httpMethod = "POST"
        let key = "trnsl.1.1.20170105T183003Z.a061e235d7abde36.51b76f0ff88678b7d1cdd254edd2951b4fb00dbf"
        let postString = "key=" + key + "&text=" + textToTranslate! + "&lang=en-ru"
        request.httpBody = postString.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request) { [weak weakSelf = self] data, response, error in
            guard let data = data, error == nil else {               // check for fundamental networking error
                print("error=\(error)")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {   // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(response)")
            }

            var parsedObject: Any?
            do {
                parsedObject = try JSONSerialization.jsonObject(with: data,options: JSONSerialization.ReadingOptions.allowFragments)
            }
            catch let error {
                print ("error: \(error)")
            }

            if let source = parsedObject as? [String: Any]{
                if let text = source["text"] as? Array<String>{
                    for temp in text{
                        print(temp)
                        weakSelf?.label.text = temp
                    }
                }
            }
            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(responseString)")
        }
        task.resume()
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        textToTranslate = textField.text
        return true
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}
  • Вопрос задан
  • 373 просмотра
Решения вопроса 2
maestrro712
@maestrro712
 iOS Developer
Давайте разберемся со всем по порядку:

1. Инициализация UILabel происходит во время загрузки view из xib'a и происходит это задолго до того, как вы введете текст :)

2. Изходя из первого пункта, я думаю, вы хотели спросить, "почему ответ появляется так поздно?".
Тут уже все сказал ManWithBear . Лишь дополню, как это должно выглядеть:
DispatchQueue.main.async { [weak self] in
    self?.label.text = temp
}


3. Ну и в конце хочется дать несколько рекомендаций по код-стайлу:
а) писать именно weakSelf не стоит. просто [weak self] отлично работает. В такой ситуации код читается легче и подсветка синтаксиса работает корректнее;
б)методы с большой буквы не называют
в)если вам надо извлечь несколько optianal'ов подряд, это можно делать в одном операторе if:
if let source = parsedObject as? [String: Any], let text = source["text"] as? [String] {
    for temp in text {
        print(temp)
        self?.label.text = temp
    }
}
Ответ написан
Комментировать
ManWithBear
@ManWithBear
Swift Adept, Prague
Потому что наверняка ответ приходит в бекграунде и вы там же обновляете лейбл, а одно из главных правил iOS разработки:
С UI нужно всегда работать из main потока.

Так что оборачивайте
weakSelf?.label.text = temp в диспатч на главном потоке.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы