swiftdelegatesuitextviewdelegate

Delegate protocol functions not triggered for UITextView


I have this swift file where I'm trying to create a custom class to handle placeholders for multiple text views on one page. I prefer a separate class because I think its cleaner to handle multiple views. Problem is, the functions textViewDidEndEditing and textViewDidBeginEditing are not being called when those events occur.

I've had it successfully work by setting the PostPage to the delegate, but I don't see how I could do that with multiple UITextViews.

This is my code:

import UIKit

class PostPage: UIViewController, UITextViewDelegate {

    @IBOutlet weak var eventDescription: UITextView!
    @IBOutlet weak var eventTitle: UITextView!

    var placeholderShowing = true

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add a placeholder for the text
        let ph_descr = PlaceHolderHandler(placeholderText: "Description", textBox: eventDescription)
        eventDescription.delegate = ph_descr

        let ph_title = PlaceHolderHandler(placeholderText: "Title", textBox: eventTitle)
        eventTitle.delegate = ph_title
    }

}

 class PlaceHolderHandler: NSObject, UITextViewDelegate {

    var placeholderShowing = true
    var placeholderText = ""

    required init(placeholderText: String, textBox: UITextView) {
        super.init()
        self.placeholderText = placeholderText
        textBox.text = placeholderText
        textBox.textColor = UIColor.lightGray
    }


    // MARK:- UITextViewDelegates

    public func textViewDidBeginEditing(_ textView: UITextView) {
        if self.placeholderShowing {
            textView.text = ""
            textView.textColor = UIColor.black
            self.placeholderShowing = false
        }

    }

    public func textViewDidEndEditing(_ textView: UITextView) {
        if textView.text == "" {
            textView.text = "Description"
            textView.textColor = UIColor.lightGray
            self.placeholderShowing = true
        }
    }
 }

When I select either of the UITextViews, I'd like the corresponding function to be called, and have the text adjust accordingly.


Solution

  • You need to retain phDescr and phTitle as in your code they are local variables so get de-allocated end of viewDidLoad

    import UIKit
    
    class PostPage: UIViewController, UITextViewDelegate {
    
        @IBOutlet weak var eventDescription: UITextView!
        @IBOutlet weak var eventTitle: UITextView!
    
        var placeholderShowing = true
    
        var phDescr, phTitle:PlaceHolderHandler!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Add a placeholder for the text
            phDescr = PlaceHolderHandler(placeholderText: "Description", textBox: eventDescription)
            eventDescription.delegate = phDescr
    
            phTitle = PlaceHolderHandler(placeholderText: "Title", textBox: eventTitle)
            eventTitle.delegate = phTitle
        }
    
    }
    
    
    

    also use camelCase to name variables

    I've had it successfully work by setting the PostPage to the delegate, but I don't see how I could do that with multiple UITextView

    Off course you can set the delegate for both to PostPage and to know which 1 is intact use

    func textViewDidBeginEditing(_ textView: UITextView) {
       if textView == eventDescription {
       }
       else {  // eventTitle
       }
    }