UITextViewにPlaceHolderを折り返し有りで追加してみる

# 概要
UITextViewにプレースホルダーを追加してみました。
かつ、プレースホルダーには**折り返し**をしてくれるようにしてみました。

# はじめに
UITextViewにプレースホルダーを追加するだけのやり方であれば、
パイセン等が分かりやすくて素晴らしい記事を公開されてるので、そちらを参考にしてみてください。

[UITextViewにプレースホルダーを設定できるようにする(Swift4)](https://qiita.com/uhooi/items/40059a1d987b64fd1aa7)
[[Swift 4.2] UITextViewにプレースホルダーを追加する[iOS 12]](https://qiita.com/Riscait/items/093cab681dfc2ca9af5f)

私自身も大変参考にさせて頂きました🙇‍♂️
ありがとうございます🙇‍♂️🙇‍♂️🙇‍♂️
~~というか、ほぼほぼベースはパクらせてもらっ~~

# こんなの
まずはじめに、単純にプレースホルダーをUILabelで追加しただけであれば、
こんな感じに折り返しが効かずに見切れてしまっています。

※『UITextViewのPlaceHolderをここに表示してます。』という文言を設定
<img width="375" alt="Simulator Screen Shot - iPhone 8 - 2020-02-16 at 20.23.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218854/dbeceb3d-8f45-8e8d-a213-707cb06d14ae.png">

それがこんな感じに！
<img width="375" alt="Simulator Screen Shot - iPhone 8 - 2020-02-16 at 20.22.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218854/78240f0a-0b6b-9e71-3366-4a124d321073.png">

もちろんxib上でも折り返して表示してくれます
<img width="926" alt="スクリーンショット 2020-02-16 19.42.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218854/93200bd5-d8df-302d-0f5a-3290cc9d5db6.png">



# ソースコード
プレースホルダーの表示用として、UILabelをaddSubViewしており、
その際に、superViewであるUITextViewに対してAutolayoutの設定を入れることにより、折り返して表示してくれるようになってます。

```Swift:PlaceHolderTextView.swift
import UIKit

@IBDesignable
class PlaceHolderTextView: UITextView {
    
    private let placeHolderLabelEdgeInsets = UIEdgeInsets(top: 8, left: 5, bottom: 8, right: 5)

    private var placeHolderLabelWidthAConstraint = NSLayoutConstraint()
    private var placeHolderLabelWidth: CGFloat {
        return frame.width - (placeHolderLabelEdgeInsets.left + placeHolderLabelEdgeInsets.right)
    }

    lazy private var placeHolderLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.font = font
        label.backgroundColor = .clear
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        
        placeHolderLabelWidthAConstraint = label.widthAnchor.constraint(equalToConstant: placeHolderLabelWidth)
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: topAnchor, constant: placeHolderLabelEdgeInsets.top),
            label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: placeHolderLabelEdgeInsets.left)
        ])

        return label
    }()
    
    @IBInspectable var placeHolder: String = "" {
        didSet { reloadView() }
    }
    @IBInspectable var placeHolderColor: UIColor = .lightGray {
        didSet { reloadView() }
    }
    
    override var text: String! {
        didSet { changeVisiblePlaceHolder() }
    }
    
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        commonInit()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    private func commonInit() {
        changeVisiblePlaceHolder()
        NotificationCenter.default.addObserver(self, selector: #selector(textChanged), name: UITextView.textDidChangeNotification, object: nil)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        placeHolderLabelWidthAConstraint.constant = placeHolderLabelWidth
        placeHolderLabelWidthAConstraint.isActive = true
    }
}

extension PlaceHolderTextView {
    
    private func reloadView() {
        placeHolderLabel.text = placeHolder
        placeHolderLabel.textColor = placeHolderColor
        changeVisiblePlaceHolder()
    }
    
    private func changeVisiblePlaceHolder() {
        placeHolderLabel.isHidden = placeHolder.isEmpty || !text.isEmpty
    }
    
    @objc private func textChanged(notification: NSNotification?) {
        changeVisiblePlaceHolder()
    }
    
}
```

# おわりに
そもそも、プレースホルダーに折り返しが必要になるほどの長文を書くシチュエーションに遭遇するのでしょうか・・・🤔

# 追記
@am10 さんからのご指摘＆ご提案から、コードベースでテキスト代入時にもプレースホルダーの表示切替が可能になりました！
@yo1106 さんからのご指摘により、コードから生成時の不具合（そもそも考慮してなかった🙈）が発覚し、修正致しました。