Я работаю над представлением входа в систему и пытаюсь изменить цвет границы UITextField в Xcode / swift3, когда проверка текстового поля не выполняется. UITextField должен получить красный цвет границы.

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

Это мой LoginViewController.swift :

import Foundation
import UIKit

class LoginViewController : UIViewController, UITextFieldDelegate  {

@IBOutlet weak var userEmailTextField: UITextField!
@IBOutlet weak var userPasswordTextField: UITextField!
override func viewDidLoad() {

    super.viewDidLoad()

}

// login button action
@IBAction func loginButtonTabbed(_ sender: Any) {

    // getting values from text fields
    let userEmail = userEmailTextField.text;
    let userPassword = userPasswordTextField.text;

    // set enpoind data
    let requestURL = NSURL(string: Constants.apiUrl)

    //creating a task to send the post request
    var request = URLRequest(url: requestURL as! URL)

    request.httpMethod = "POST"

    let postString = "cmd=addUser&email="+userEmail!+"&password="+userPassword!

    request.httpBody = postString.data(using: .utf8)

    let task = URLSession.shared.dataTask(with: request) { 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)")
        }

        do {

            let json = try? JSONSerialization.jsonObject(with: data, options: [])

            // store json response to dictionary
            if let dictionary = json as? [String: Any] {

                // check if we got validation errors
                if let nestedDictionary = dictionary["validation"] as? [String: Any] {

                    // display validation messages on device
                    if let emailMsg = nestedDictionary["Email"] as? String {                            // change color of textfield
                        self.userEmailTextField.errorField()


                    }

                }

            }

        } catch let error as NSError {
            print(error)
        }

    }
    //executing the task
    task.resume()

}

}

И расширение UITextField UITextField.swift :

import Foundation
import UIKit

extension UITextField {

    func errorField(){
        self.layer.borderColor = UIColor(red: 255/255.0, green: 59/255.0, blue: 48/255.0, alpha: 1.0).cgColor
        self.layer.borderWidth = 1.0;
    }

}
0
Yolo 4 Июл 2017 в 21:56
«Мне нужно снова сфокусировать текстовое поле электронной почты, прежде чем оно станет красной рамкой». <- Что ?! Мне непонятно, чего ты хочешь ...
 – 
Honey
4 Июл 2017 в 23:26
При запуске симулятора я ввожу электронное письмо в текстовое поле электронной почты и пароль в поле пароля, в то время как последнее находится в фокусе, а затем нажимая кнопку отправки, ничего не происходит. Мне нужно снова вставить поле электронной почты, прежде чем цвет границы станет красным. Я хочу, чтобы он стал красным при переходе на вкладку «Отправить», если есть ошибка проверки.
 – 
Yolo
4 Июл 2017 в 23:34
Вы реализуете какой-либо из методов делегата textFields? Если да, то также покажите их код. В противном случае это должно было сработать ...
 – 
Honey
5 Июл 2017 в 00:11
Нет. Не то, чтобы я знал :) Я отредактировал сообщение, чтобы включить весь контроллер представления. У меня больше ничего нет.
 – 
Yolo
5 Июл 2017 в 00:20
Ха! только что разобрался в вопросе! Когда вы выполняете сетевой вызов, это всегда происходит в фоновом режиме ... поэтому для выполнения каких-либо обновлений пользовательского интерфейса вам необходимо находиться в основной очереди. Просто поместите self.userEmailTextField.errorField() внутрь DispatchQueue.main.async {...}, чтобы это было сделано немедленно
 – 
Honey
5 Июл 2017 в 00:33

1 ответ

Лучший ответ

Когда вы выполняете сетевой вызов, это всегда происходит в фоновом режиме ... поэтому для выполнения каких-либо обновлений пользовательского интерфейса вам необходимо находиться в основной очереди. Просто поместите self.userEmailTextField.errorField() внутрь DispatchQueue.main.async {...}, чтобы это было сделано немедленно.

Также не очень хорошо тестировал ваш код. Почему?

Даже в вашем текущем коде граница все равно станет красной, но она станет красной примерно через 6-7 секунд (это может занять меньше или больше для вас) ... потому что она запускается из фонового потока.

Я не понимаю, почему при повторном нажатии на текстовое поле сразу появляется красная граница !? Вот что, как я догадываюсь , происходит:

Из фонового потока вы обновляете модель , т. Е. Меняете цвет textField, который ставит в очередь пользовательский интерфейс / представление для обновления. ... но поскольку мы находимся в фоновой очереди, обновление пользовательского интерфейса может занять несколько секунд

Но затем вы сразу же нажали на textField и заставили сверхбыстрое чтение textField и всех его свойств, включая границу, из основного потока (фактические действия пользователя всегда обрабатываются через основной поток) ... которые, хотя еще не красный на экране, но поскольку он красный на модели, он будет считывать с него и сразу же изменит цвет на красный.

1
Honey 5 Июл 2017 в 08:48