Я понимаю, что все обновления пользовательского интерфейса должны выполняться из основного потока.
Но чисто ради более глубокого понимания того, как работают GCD и диспетчеризация main:
У меня есть кнопка, которая запускает сетевой вызов, и в его завершенииHandler я в конечном итоге делаю:
self.layer.borderColor = UIColor(red: 255/255.0, green: 59/255.0, blue: 48/255.0, alpha: 1.0).cgColor
self.layer.borderWidth = 3.0
Для изменения цвета требуется 6-7 секунд. Очевидно, что если запустить приведенный выше код из основного потока, он немедленно изменит цвет границы.
Вопрос1, хотя у меня нет НИКАКОГО другого кода для запуска, почему изменения пользовательского интерфейса не происходят сразу из фонового потока? Чего ждать?
Интересно, однако, что если я нажму кнопку, чтобы сделать сетевой вызов, а затем нажму на само текстовое поле (до 6-7 секунд), цвет границы немедленно изменится.
Это происходит из-за:
Из фонового потока я обновил модель, т.е. изменил цвет textField, который ставит в очередь обновление пользовательского интерфейса/представления... но, поскольку мы находимся в фоновой очереди, обновление пользовательского интерфейса может занять несколько секунд.
Но затем я сразу же нажал на textField и принудительно быстро прочитал текстовое поле и все его свойства, включая границу, из основного потока (фактические пользовательские касания всегда обрабатываются через основной поток) ... которые, хотя еще не красный на экране, но поскольку он красный на модели, он будет считывать с него и немедленно менять цвет на красный.
Вопрос 2. Верно ли это наблюдение?
Если я не нажму и просто подожду:
Если я нажму:
Мой полный код выглядит следующим образом:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBAction func isValid(_ sender: Any) {
let userEmail = textField.text
let requestURL = NSURL(string: "https://jsonplaceholder.typicode.com")
var request = URLRequest(url: requestURL as! URL)
request.httpMethod = "POST"
let postString = "Anything"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
}
do {
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let _ = json as? [String: Any] {
self.textField.layer.borderColor = UIColor(red: 255/255.0, green: 59/255.0, blue: 48/255.0, alpha: 1.0).cgColor
self.textField.layer.borderWidth = 3.0
}
} catch let error as NSError {
print(error)
}
}
task.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
}
}