はじめに
Obj-C時代から思っていましたが、UITextFieldにはデフォルトでプレースホルダーがあるのに、なぜUITextViewにはないのでしょうか…。
ということで、こちらの記事を参考にさせていただき、Swift4でUITextViewにプレースホルダーを実装します。
プレースホルダーの実装
@IBInspectable
を使うことにより、ストーリーボード上で placeHolder
の値を指定できるようにしています。
型推論するとIBInspectableが効かないようなので、明示的に String
を指定します。
self.placeHolderLabel.textColor
の値が中途半端なのは、UITextFieldのデフォルト値がそのようになっているためです。
PlaceHolderTextView.swift
import UIKit
@IBDesignable class PlaceHolderTextView: UITextView {
// MARK: Stored Instance Properties
@IBInspectable private var placeHolder: String = "" {
willSet {
self.placeHolderLabel.text = newValue
self.placeHolderLabel.sizeToFit()
}
}
private lazy var placeHolderLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 6.0, y: 6.0, width: 0.0, height: 0.0))
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.font = self.font
label.textColor = UIColor(red: 0.0, green: 0.0, blue: 0.0980392, alpha: 0.22)
label.backgroundColor = .clear
self.addSubview(label)
return label
}()
// MARK: Initializers
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: View Life-Cycle Methods
override func awakeFromNib() {
super.awakeFromNib()
changeVisiblePlaceHolder()
NotificationCenter.default.addObserver(
self,
selector: #selector(textChanged),
name: .UITextViewTextDidChange,
object: nil
)
}
// MARK: Other Private Methods
private func changeVisiblePlaceHolder() {
self.placeHolderLabel.alpha = (self.placeHolder.isEmpty || !self.text.isEmpty) ? 0.0 : 1.0
}
@objc private func textChanged(notification: NSNotification?) {
changeVisiblePlaceHolder()
}
}
Swiftのバージョンが新しい場合、 .UITextViewTextDidChange
を UITextView.textDidChangeNotification
に差し替えてください。