Невозможно проверить, пусто ли текстовое поле - PullRequest
0 голосов
/ 14 июля 2020

Я публикую это после того, как попробовал все .isEmpty найденные мной решения.

Я не могу обнаружить значение в textField. У меня есть ячейки, для которых установлено значение cell.selectionStyle = .none. Эти ячейки имеют label и textFields.

Я дал идентификаторы ячеек:

let cell = addRestaurant.dequeueReusableCell(withIdentifier: String(describing: RestaurantAddViewCells.self), for: indexPath) as! RestaurantAddViewCells

Моя цель - иметь кнопку, которая проверяет, пусто ли какое-либо поле при нажатии.

let saveButton = UIBarButtonItem(image: UIImage(named: "save"), style: .plain, target: self, action: #selector(saveRestaurant))

Вот как я пытаюсь проверить, пусты ли текстовые поля или нет:

@objc func saveRestaurant() {
    if let indexPath = addRestaurant.indexPathForSelectedRow {   
        let cell = addRestaurant.cellForRow(at: indexPath) as! RestaurantAddViewCells
        if (cell.nameTextField.text == "" || cell.typeTextField.text == "" || cell.locationTextField.text == "" || cell.hotelPhoneText.text == "") {
            let saveAlertController = UIAlertController(title: "Fields Empty", message: "fill all fields", preferredStyle: .alert)
            let saveAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            saveAlertController.addAction(saveAction)
            self.present(saveAlertController, animated: false, completion: nil)
        }
        else { }
    }
}

Однако ничего не происходит

Я пробовал и прокомментировал cell.selectionStyle = .none , все еще без эффекта

Здесь addRestaurant - это tableView в том же файле, а RestaurantAddViewCells - это класс, содержащий свойства для labels, textFields

UPDATE - вот что я делаю в my cellForRowAt, образец для первых двух ячеек

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.row {
        case 0:
            let cell = addRestaurant.dequeueReusableCell(withIdentifier: String(describing: RestaurantAddViewCells.self), for: indexPath) as! RestaurantAddViewCells
            view.addSubview(cell.contentView)
            view.addSubview(cell.hotelImage)
            view.addSubview(cell.imageButton)
            view.addSubview(cell)
            
            cell.imageButton.translatesAutoresizingMaskIntoConstraints = false
            cell.hotelImage.translatesAutoresizingMaskIntoConstraints = false
            //set the cell height
            cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 200).isActive = true
            
            //set the hotelImage
            
            cell.hotelImage.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width).isActive = true
            cell.hotelImage.heightAnchor.constraint(equalToConstant: 200).isActive = true
            
            
            cell.hotelImage.leadingAnchor.constraint(equalTo: cell.leadingAnchor).isActive = true
            cell.hotelImage.topAnchor.constraint(equalTo: cell.topAnchor).isActive = true
            
            // pin it
            //No need to pin it as width is already pinned to to lead and trail of screen
            cell.imageButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
            cell.imageButton.widthAnchor.constraint(equalToConstant: 30).isActive = true
            
            cell.imageButton.centerXAnchor.constraint(equalTo: cell.centerXAnchor).isActive = true
            cell.imageButton.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
            cell.imageButton.image = UIImage(named: "photo")
            
            return cell
            
        case 1:
            let cell = addRestaurant.dequeueReusableCell(withIdentifier: String(describing: RestaurantAddViewCells.self), for: indexPath) as! RestaurantAddViewCells
            
            cell.nameTextFiled.tag = 1
            cell.nameTextFiled.delegate = self
            cell.nameTextFiled.becomeFirstResponder()
            cell.selectionStyle = .none
            cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
            view.addSubview(cell.nameLabel)
            view.addSubview(cell.nameTextFiled)
            view.addSubview(cell)
            view.addSubview(cell.contentView)
            cell.nameLabel.translatesAutoresizingMaskIntoConstraints = false
            cell.nameTextFiled.translatesAutoresizingMaskIntoConstraints = false
            cell.nameTextFiled.heightAnchor.constraint(equalToConstant: 50).isActive = true
            cell.nameLabel.text = "Name:"
            
            
            
            //Define custom fonts
            
            let font = UIFont(name: "Rubik-Medium", size: 18)
            let dynamicFonts = UIFontMetrics(forTextStyle: .body)
            cell.nameLabel.font = dynamicFonts.scaledFont(for: font!)
            cell.nameTextFiled.font = dynamicFonts.scaledFont(for: font!)
            cell.nameTextFiled.borderStyle = .roundedRect
            cell.nameTextFiled.placeholder = "Enter Your Name"
            
            
            
            let stackName = UIStackView()
            view.addSubview(stackName)
            stackName.alignment = .top
            stackName.axis = .vertical
            stackName.spacing = 5.0
            stackName.distribution = .fill
            stackName.translatesAutoresizingMaskIntoConstraints = false
            stackName.addArrangedSubview(cell.nameLabel)
            stackName.addArrangedSubview(cell.nameTextFiled)
            
            
            
            stackName.topAnchor.constraint(equalTo: cell.topAnchor, constant: 10).isActive = true
            stackName.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 10).isActive = true
            stackName.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
            
            cell.nameTextFiled.trailingAnchor.constraint(equalTo: stackName.trailingAnchor).isActive = true
            
            return cell
            

Вот как выглядит мой обновленный RestaurantAddViewCells с вводом от одного члена здесь

class RestaurantAddViewCells: UITableViewCell, UITextFieldDelegate, UITextViewDelegate {
    
    var nameLabel: UILabel = UILabel()
    var nameTextFiled: RoundedTextFields = RoundedTextFields()
    
    var typeLabel: UILabel = UILabel()
    var typeTextField: RoundedTextFields = RoundedTextFields()
    
    var locationLabel: UILabel = UILabel()
    var locationTextField: RoundedTextFields = RoundedTextFields()
    
    var imageButton: UIImageView = UIImageView()
    var hotelImage: UIImageView = UIImageView()
    
    var hotelDescriptionLabel: UILabel = UILabel()
    var hotelTextDescription: UITextView = UITextView()
    
    var hotelPhonelabel: UILabel = UILabel()
    var hotelPhoneText: RoundedTextFields = RoundedTextFields()
    
    
    var isEmptyTextFields: Bool {
        return nameTextFiled.text!.isEmpty || typeTextField.text!.isEmpty || locationTextField.text!.isEmpty || hotelTextDescription.text!.isEmpty || hotelPhoneText.text!.isEmpty
    }
    

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    
    
    

}

UPDATE 2 - так вот мое обновление при попытке задайте вопрос еще раз, у меня есть tableview, где в каждой ячейке есть textfields, когда я нажимаю кнопку, прежде чем делать что-либо с данными, я хочу проверить, заполнены ли поля или нет, как я могу сделать это, теперь в соответствии с моим дизайном я использую класс для определения правильного представления связывает и вызывает их, а затем задает значения, в которых я использую tableView, я использую cellForRowAt для определения ограничений и предоставления значений меткам et c, но как я могу успешно получить к ним доступ за пределами cellForRowAt, чтобы проверить текущее состояние, с полностью изменив дизайн проекта

UPDATE 3 - кажется, если бы я сделал то же самое в раскадровке и добавил выходы к той же функции, он был способен обнаруживать изменение состояния текстового поля, если оно пуст или нет, в случае попытки сделать это программно, он не может обнаружить изменение состояния текстового поля с пустого на непустое, но у меня все еще нет возможности проверить, как в javascript, если текстовые поля пусты или не при нажатии кнопки

Обновление 4 - теперь я использую приведенный ниже код при нажатии кнопки, но по какой-то странной причине я не могу обнаружить введенный текст, он всегда возвращается пустым, даже если там есть текст

@objc func saveRestaurant(sender: AnyObject) {
        
        let cell = addRestaurant.dequeueReusableCell(withIdentifier: String(describing: RestaurantAddViewCells.self)) as! RestaurantAddViewCells
        
        if cell.nameTextFiled.text == "" || cell.typeTextField.text == "" || cell.locationTextField.text == "" || cell.hotelPhoneText.text == "" || cell.hotelTextDescription.text == "" {
                let alertController = UIAlertController(title: "Oops", message: "We can't proceed because one of the fields is blank. Please note that all fields are required.", preferredStyle: .alert)
                let alertAction = UIAlertAction(title: "OK", style: .default, handler: nil)
                alertController.addAction(alertAction)
                present(alertController, animated: true, completion: nil)
           // addRestaurant.reloadData()
                return
            }
        
        else {
            
            print("Name: \(cell.nameTextFiled.text ?? "")")
            print("Type: \(cell.typeTextField.text ?? "")")
            print("Location: \(cell.locationTextField.text ?? "")")
            print("Phone: \(cell.hotelPhoneText.text ?? "")")
            print("Description: \(cell.hotelTextDescription.text ?? "")")
            
            dismiss(animated: true, completion: nil)
        }
     
    }

Обновление 5 - вот что наконец-то сработало, но очень долго и не очень хорошо, может ли кто-нибудь предложить l oop для прохождения всего indexPath

  @objc func saveRestaurant(sender: AnyObject) {

        let index = IndexPath(row: 1, section: 0)
        let cell: RestaurantAddViewCells = self.addRestaurant.cellForRow(at: index) as! RestaurantAddViewCells
        let nameVal = cell.nameTextFiled.text!
        
        let index1 = IndexPath(row: 2, section: 0)
        let cell2: RestaurantAddViewCells = self.addRestaurant.cellForRow(at: index1) as! RestaurantAddViewCells
        let typeVal = cell2.typeTextField.text!
        
        let index2 = IndexPath(row: 3, section: 0)
        let cell3: RestaurantAddViewCells = self.addRestaurant.cellForRow(at: index2) as! RestaurantAddViewCells
        let locationVal = cell3.locationTextField.text!
        
        let index3 = IndexPath(row: 4, section: 0)
        let cell4: RestaurantAddViewCells = self.addRestaurant.cellForRow(at: index3) as! RestaurantAddViewCells
        let phoneVal = cell4.hotelPhoneText.text!
        
        let index4 = IndexPath(row: 5, section: 0)
        let cell5: RestaurantAddViewCells = self.addRestaurant.cellForRow(at: index4) as! RestaurantAddViewCells
        let descVal = cell5.hotelTextDescription.text!
        
        if(nameVal == "" || typeVal == "" || locationVal == "" || phoneVal == "" || descVal == "") {
            let saveAlertController = UIAlertController(title: "Fields Empty", message: "fill all fields", preferredStyle: .alert)
            let saveAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
            saveAlertController.addAction(saveAction)
            self.present(saveAlertController, animated: false, completion: nil)
            //  return
        }
        else {
            
            print("Name: \(nameVal)")
            print("Type: \(typeVal)")
            print("Location: \(locationVal)")
            print("Phone: \(phoneVal)")
            print("Description: \(descVal)")
            self.navigationController?.popViewController(animated: false)
            
        }
 
    }
        

Ответы [ 2 ]

0 голосов
/ 14 июля 2020

Прежде всего, добавьте вычисляемое свойство в RestaurantAddViewCells, которое вернет, если какой-либо из textFields в cell пуст, т.е.

class RestaurantAddViewCells: UITableViewCell {
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var typeTextField: UITextField!
    
    var isEmptyTextFields: Bool {
        return nameTextField.text!.isEmpty || typeTextField.text!.isEmpty
    }
}

Теперь ваш метод saveRestaurant() будет от oop до numberOfCells. Получите cell для каждого row и проверьте, возвращает ли isEmptyTextFields true. В этом случае вам нужно показать alert.

@objc func saveRestaurant() {
    let numberOfCells = 6
    var isAnyTextFieldEmpty = false
    
    (0..<numberOfCells).forEach {
        let cell = tableView.cellForRow(at: IndexPath(row: $0, section: 0)) as! RestaurantAddViewCells
        isAnyTextFieldEmpty = isAnyTextFieldEmpty || cell.isEmptyTextFields
    }
    
    if isAnyTextFieldEmpty {
        //Show alert...
    } else {
        //....
    }
}
0 голосов
/ 14 июля 2020

Я постараюсь дать вам ответ как можно проще.

Проблема

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

Решение

У нас есть текстовое поле в наших ячейках, и нам нужно, чтобы все вводимые пользователем данные где-то хранились, скажем, словарь IndexPath как ключ и String как значение. Что-то вроде var inputs:[IndexPath: String] = [:]. Каждый раз, когда пользователь что-то вводит и как только выходит из текстового поля, мы сохраняем этот ввод в нашем словаре напротив его indexPath ячейки. когда пользователь нажимает кнопку, мы пропустим oop и проверим, какое текстовое поле пусто

Здесь очень простой пример

import UIKit

class TextFieldTableViewCell: UITableViewCell {
    lazy var textField: UITextField = {
        let textField = UITextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.placeholder = "Enter your text here"
        return textField
    } ()
    lazy var label: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.setContentHuggingPriority(.required, for: .horizontal)
        return label
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.setupView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

extension TextFieldTableViewCell {

    //MARK: Private
    private func setupView() {
        selectionStyle = .none
        contentView.addSubview(label)
        contentView.addSubview(textField)
        label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8).isActive = true
        label.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 8).isActive = true
        label.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -8).isActive = true
        label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true

        textField.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: 8).isActive = true
        textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8).isActive = true
        textField.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 8).isActive = true
        textField.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -8).isActive = true
        textField.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true

    }

}

class ViewController: UIViewController {

    private lazy var tableView: UITableView = {
        let tableView = UITableView.init(frame: .zero, style: .grouped)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        return tableView
    }()

    private var inputs: [IndexPath: String] = [:]

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(tableView)
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        tableView.dataSource = self
        tableView.register(TextFieldTableViewCell.self, forCellReuseIdentifier: "TextFieldTableViewCell")
        title = "Some random title"
        let barbutton = UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(saveAction(_:)))
        navigationItem.rightBarButtonItem = barbutton
    }

    @objc
    func saveAction(_ sender: UIBarButtonItem) {
        view.endEditing(true)
        for i in 0 ..< tableView.numberOfSections {
            for j in 0 ..< tableView.numberOfRows(inSection: i) {
                let indexPath = IndexPath.init(row: j, section: i)
                print("Input at indexPath: Row: \(indexPath.row), Section: \(indexPath.section)")
                if let input = inputs[indexPath], input.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 {
                    print(input)
                }
                else {
                    print("user has not input any value or kept it empty")
                }
                print("__________")
            }
        }
    }


}

extension ViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        30
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldTableViewCell", for: indexPath) as? TextFieldTableViewCell ?? TextFieldTableViewCell.init(style: .default, reuseIdentifier: "TextFieldTableViewCell")
        cell.label.text = "Row: \(indexPath.row)"
        cell.textField.delegate = self
        cell.textField.text = inputs[indexPath]
        return cell
    }

}

extension ViewController: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        if let cell = textField.superview?.superview as? TextFieldTableViewCell, let indexPath = tableView.indexPath(for: cell) {
            inputs[indexPath] = textField.text
        }
    }
}

EDIT

После комментариев OPs, вот решение, которое будет работать для OP

Решение: Поскольку OP имеет только 6 ячеек, мы можем кэшировать их в словаре и возвращаться из словаря, когда это необходимо. (Мы делаем это только из-за небольшого количества ячеек таблицы и структуры OP. Я не рекомендую это решение)

Добавить новый словарь в ваш контроллер просмотра

private var cachedCell: [IndexPath: TextFieldTableViewCell] = [:]

Изменить ячейку для (Обратите внимание, что вы не должны повторно использовать ячейки tableview, поскольку мы кэшируем их в нашем словаре cachedCell, иначе это может привести к неизвестному. Я никогда не рекомендую кэшировать ячейки как мной, так и другими разработчиками)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = cachedCell[indexPath] {
        return cell
    }
    let cell = TextFieldTableViewCell.init(style: .default, reuseIdentifier: "TextFieldTableViewCell")
    cell.label.text = "Row: \(indexPath.row)"
    cell.textField.delegate = self
    cell.textField.text = inputs[indexPath]
    cachedCell[indexPath] = cell
    return cell
}

Измените действие сохранения на

@objc
func saveAction(_ sender: UIBarButtonItem) {
    view.endEditing(true)
    for (indexPath, cell) in cachedCell {
        print("Input at indexPath: Row: \(indexPath.row), Section: \(indexPath.section)")
        if let input = cell.textField.text, input.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 {
            print(input)
        }
        else {
            print("user has not input any value or kept it empty")
        }
        print("__________")
    }
}

Если у вас есть другие вопросы, вы можете задать их в разделе комментариев.

Happy Coding

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...