3
votes

I currently have a text view with placeholder text that dissapears whenever a user taps on the text view and the text in the textview reappears whenever the first responder is resigned, if the text view is empty. (Heres the code I use for that in case anyone wants to use it)

*Note, first set the text color of the textview to light gray and set the placeholder text. Then use these methods:

func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
    //If it begins editing, then set the color to black
    if (textView.tag == 0){
        textView.text = ""
        textView.textColor = .black
        textView.tag = 1
    }
    return true
}


func textViewDidEndEditing(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.text = "Example: I started my career as a street wear model based in Maryland. After 3 years of working with some of the top companies there, I moved to LA, where I currently reside. I’ve been featured in shows, 12 magazines, commercials, and a number of music videos. Now, Im currently looking to continue working with clothing companies and campaigns."
        textView.textColor = .lightGray
        textView.tag = 0
    }
}

I wanted to step things up a notch. Right now, the text disappears whenever the text view becomes the first responder. I want the text to disappear whenever the user actually starts typing, not just when the text view is selected. When the screen appears, I automatically set the first responder to the text view and I plan on keeping it that way. But because its automatically set, you're not able to see the placeholder text. I only want the text view to disappear whenever the user presses a key, not because its selected.

2

2 Answers

4
votes

Here's the code

class ViewController: UIViewController {

    @IBOutlet weak var textView: UITextView!
    let placeholder = "Example: I started my career as a street wear model based in Maryland. After 3 years of working with some of the top companies there, I moved to LA, where I currently reside. I’ve been featured in shows, 12 magazines, commercials, and a number of music videos. Now, Im currently looking to continue working with clothing companies and campaigns."
    let start = NSRange(location: 0, length: 0)
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        textView.text = placeholder
    }
}

extension ViewController: UITextViewDelegate {
    func textViewDidChangeSelection(_ textView: UITextView) {
        // Moves cursor to start when tapped on textView with placeholder
        if textView.text == placeholder {
            textView.selectedRange = start
        }
    }
    func textViewDidChange(_ textView: UITextView) {
        // Manages state of text when changed
        if textView.text.isEmpty {
            textView.text = placeholder
            textView.textColor = .lightGray
        } else if textView.text != placeholder {
            textView.textColor = .black
        }
    }
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        // Called when you're trying to enter a character (to replace the placeholder)
        if textView.text == placeholder {
            textView.text = ""
        }
        return true
    }
}

Updated #1: Maximum length

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    // Called when you're trying to enter a character (to replace the placeholder)
    if textView.text == placeholder {
        textView.text = ""
    } else if textView.text.count >= 175 && text.count > 0 {
        // Now it can delete symbols but can't enter new
        return false
    }
    return true
}

There's slight bug when trying to clear textView by holding erase button. Placeholder is not showing. Method textViewDidChange somehow is not called (goes out of sync with shouldChangeTextIn). Possible workaround https://stackoverflow.com/a/9169556/5228431

4
votes

Lets assume you have a placeholder text as this,

let placeholderText = "Example: I started my career as a street wear model based in Maryland. After 3 years of working with some of the top companies there, I moved to LA, where I currently reside. I’ve been featured in shows, 12 magazines, commercials, and a number of music videos. Now, Im currently looking to continue working with clothing companies and campaigns."

And you are setting this text to textView in storyboard or in viewDidLoad before calling becomeFirstResponder of textView.

Then in these two delegate methods you can achieve this behavior as below,

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if textView.text == placeholderText {
        textView.text = ""
    }
    return true
}

func textViewDidEndEditing(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.text = placeholderText
    }
}

Currently you are clearing the text in textViewShouldBeginEditing so, that is the main reason you are not able to see that text. You should remove clearing the text there but you can keep changing the colors etc as it is.