Swift: отключить кнопку панели для текста с пробелами/новой строкой в ​​UITextView с текстом-заполнителем

У меня есть ViewController с UITextView и элементом кнопки «Отправить» на панели навигации, который отправляет текст в textView. Поскольку UITextView не поддерживает текст-заполнитель, такой как UITextField, я обрабатываю его самостоятельно с помощью следующего кода, который находится в методе UITextViewDelegate, shouldChangeTextInRange.

Примечание. Следующий код, который я написал до сих пор, также активирует кнопку «Отправить» для пробелов/символов новой строки. Но вот с чем мне нужна помощь:

Как я могу отключить кнопку "Отправить", если textView содержит только пробелы или символы новой строки, но включить ее в противном случае, при этом также правильно установив/удалив текст-заполнитель?

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

    // Combine the postTextView text and the replacement text to
    // create the updated text string
    let currentText : NSString = textView.text
    let updatedText = currentText.stringByReplacingCharactersInRange(range, withString:text)

    // If the updated textView text will be empty, disable the send button,
    // set the placeholder text and color, and set the cursor to the beginning of the text view
    if updatedText.isEmpty {
        sendBarButton.enabled = false
        textView.text = "Write something..."
        textView.textColor = UIColor.lightGrayColor()
        textView.selectedTextRange = textView.textRangeFromPosition(textView.beginningOfDocument, toPosition: textView.beginningOfDocument)
        return false
    }

    // If the textView's placeholder is showing (i.e.: the textColor is light gray for placeholder text) 
    // and the length of the replacement string is greater than 0, 
    // clear the text view and set its color to black to prepare for the user to enter text
    else if (textView.textColor == UIColor.lightGrayColor() && !(text.isEmpty)) {
        sendBarButton.enabled = true
        textView.text = nil
        textView.textColor = UIColor.blackColor()
    }

    return true
}

ОБНОВЛЕНИЕ: я понимаю, что следующий код может использоваться для обрезки/распознавания пробелов и символов новой строки, но не уверен, как применить его здесь в этом случае: stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).isEmpty

Спасибо за вашу помощь.


person DiligentDev    schedule 21.11.2016    source источник


Ответы (2)


Я буду делать так. Я добавил заполнитель UILabel к UITextView, который я буду показывать или скрывать в зависимости от количества введенных символов (0 или не ноль).

Вот пример.

Это синтаксис Swift 3.x. Он будет работать только на Xcode 8.x.

Я только что использовал еще несколько методов делегата UITextView, как показано в моем расширении ниже.

import UIKit

class ViewController: UIViewController {

    var placeHolderLabel:UILabel!
    @IBOutlet weak var myTextView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        placeHolderLabel = UILabel(frame: CGRect(x:5, y:5, width:240, height:22))
        placeHolderLabel.text = "Send Placeholder"

        //Set the font same as your textView font
        placeHolderLabel.font = UIFont.systemFont(ofSize: 15.0)

        //set the placeholder color
        placeHolderLabel.textColor = UIColor.lightGray

        myTextView.addSubview(placeHolderLabel)

        //Initially disable the send button
        sendButton.isEnabled = false
    }
}

// MARK: - TextView Delegates
extension ViewController:UITextViewDelegate {

    // Will handle the case for white spaces and will keep the send button disabled
    func textViewDidChange(_ textView: UITextView) {
        if(textView.text.characters.count != 0) {
            if textView.text.characters.count > 1 {
            return
            }
            textView.text = textView.text.trimmingCharacters(in: CharacterSet.whitespaces)
            if textView.text.characters.count == 0 {
                placeHolderLabel.isHidden = false
                print("Disable Button")
                sendButton.isEnabled = false
            } else {
                placeHolderLabel.isHidden = true
                print("Enable Button")
                sendButton.isEnabled = true
            }
        }
        else {
            placeHolderLabel.isHidden = false
            print("Disable Button")
            sendButton.isEnabled = false
        }
    }

    // You can modify this, as I just made my keyboard to return whenever return key is pressed.
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        if(text == "\n") {
            textView.resignFirstResponder()
            return false
        }
        return true
    }

    func textViewDidBeginEditing(_ textView: UITextView) {
        if(textView.text.characters.count != 0) {
            placeHolderLabel.isHidden = true
        }
        else {
            placeHolderLabel.isHidden = false
        }
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        if(textView.text.characters.count != 0) {
            placeHolderLabel.isHidden = true
        }
        else {
            placeHolderLabel.isHidden = false
        }
    }
}
person Rajan Maheshwari    schedule 21.11.2016
comment
Спасибо, Раджан, но я считаю, что это все еще включает кнопку панели для пробельных символов. - person DiligentDev; 21.11.2016
comment
Для этого нам нужно написать некоторую логику, просто обрезать ваши символы для пробелов. Я обновлю код через минуту - person Rajan Maheshwari; 21.11.2016
comment
Спасибо. Да, я могу использовать метод stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) для обрезки пробелов и символов новой строки, но мне нужно, чтобы кнопка панели отправки была отключена для этих символов, пока не будет введен какой-либо другой символ. - person DiligentDev; 21.11.2016
comment
@DiligentDev Обновлен код и образец ссылки с учетом ваших требований к пробелам. - person Rajan Maheshwari; 21.11.2016
comment
Спасибо. Хотя ваше решение не сработало для меня, я смог использовать часть вашего ответа, чтобы найти собственное простое решение. Смотрите мой опубликованный ответ. Спасибо за вашу помощь! - person DiligentDev; 21.11.2016

Я смог использовать часть ответа @Rajan Maheshwari, чтобы создать простое решение моей собственной проблемы (я думаю, что его можно даже упростить еще больше:

var placeholderLabel: UILabel!

func viewDidLoad() {
        placeholderLabel = UILabel(frame: CGRect(x: 5, y: 5, width: 240, height: 18))
        placeholderLabel.text = "Placeholder text..."
        placeholderLabel.textColor = UIColor.lightGrayColor()
        placeholderLabel.sizeToFit()
        postTextView.addSubview(placeholderLabel)
}

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

        let currentText: NSString = textView.text
        let updatedText = currentText.stringByReplacingCharactersInRange(range, withString:text)
        let trimmedText = updatedText.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

        if !updatedText.isEmpty {
            // Contains any text: hide placeholder
            placeholderLabel.hidden = true
            if trimmedText.isEmpty {
                // Only whitespace and newline characters: disable button
                sendBarButton.enabled = false
            } else {
                // No whitespace- and newline-only characters: enable button
                sendBarButton.enabled = true
            }
        } else {
            // No text at all: show placeholder, disable button
            placeholderLabel.hidden = false
            sendBarButton.enabled = false
        }
        return true
    }

Кредит: благодаря помощи @Rajan Maheshwari!

person DiligentDev    schedule 21.11.2016