検証環境:
Xcode 11.3
Swift 5.1.3
UITextView にプレースホルダーを設定できるカスタムビューを作成した。
import UIKit @IBDesignable open class PlaceHolderTextView: UITextView { @IBInspectable open var placeHolderText: String = "" { didSet { placeHolderLabel.text = placeHolderText updatePlaceHolder() } } open var placeHolderLabel: UILabel = .init() open override func awakeFromNib() { super.awakeFromNib() configure() } open override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() configure() } // text プロパティに直接文字列をセットした場合、textViewDidChange は呼ばれないので override している open override var text: String! { didSet { updatePlaceHolder() } } deinit { NotificationCenter.default.removeObserver(self) } private func configure() { placeHolderLabel.lineBreakMode = .byWordWrapping placeHolderLabel.numberOfLines = 0 placeHolderLabel.font = font placeHolderLabel.textColor = .lightGray addSubview(placeHolderLabel) placeHolderLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ placeHolderLabel.topAnchor.constraint(equalTo: topAnchor, constant: textContainerInset.top), placeHolderLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: textContainer.lineFragmentPadding), placeHolderLabel.widthAnchor.constraint(equalTo: widthAnchor) ]) updatePlaceHolder() NotificationCenter.default.addObserver( self, selector: #selector(textViewDidChange(_:)), name: UITextView.textDidChangeNotification, object: nil) } private func updatePlaceHolder() { placeHolderLabel.isHidden = placeHolderText.isEmpty || !text.isEmpty } @objc private func textViewDidChange(_ notification: Notification) { updatePlaceHolder() } }