I have a custom UITextView
that shows a placeholder, like so:
extension UITextView {
private class PlaceholderLabel: UILabel { }
private var placeholderLabel: PlaceholderLabel {
if let label = subviews.compactMap( { $0 as? PlaceholderLabel }).first {
return label
} else {
let label = PlaceholderLabel(frame: .zero)
label.font = font
addSubview(label)
return label
}
}
@IBInspectable
var placeholder: String {
get {
return subviews.compactMap( { $0 as? PlaceholderLabel }).first?.text ?? ""
}
set {
let placeholderLabel = self.placeholderLabel
placeholderLabel.text = newValue
placeholderLabel.numberOfLines = 0
let width = frame.width - textContainer.lineFragmentPadding * 2
let size = placeholderLabel.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude))
placeholderLabel.frame.size.height = size.height
placeholderLabel.frame.size.width = width
placeholderLabel.frame.origin = CGPoint(x: textContainer.lineFragmentPadding, y: textContainerInset.top)
textStorage.delegate = self
}
}
@IBInspectable
var placeholderColor: UIColor? {
get {
self.placeholderColor
}
set {
placeholderLabel.textColor = newValue
}
}
}
extension UITextView: NSTextStorageDelegate {
public func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorage.EditActions, range editedRange: NSRange, changeInLength delta: Int) {
if editedMask.contains(.editedCharacters) {
placeholderLabel.isHidden = !text.isEmpty
}
}
}
I've put the UITextView
inside a UIView
which sits inside a UIStackView
so that I can hide it and show it as needed. It's hidden by default. However, when run the app, the text view looks like this:
When it should look like this:
I've noticed on the storyboard that the width of the UIView
is 64 when it's hidden inside the UIStackView
and 428 when it's not hidden. So I think what might be happening is that the placeholder is setup when the UIView
is 64, but isn't updated when the UIView
is shown in the UIStackView
.
What should I do to the UITextView
extension so that it shows the placeholder in its full uncut length?
I've tried adding the following below addSubview(label)
, but it hasn't helped:
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: superview!.leadingAnchor, constant: 0).isActive = true
label.trailingAnchor.constraint(equalTo: superview!.trailingAnchor, constant: 0).isActive = true
label.topAnchor.constraint(equalTo: superview!.topAnchor, constant: 0).isActive = true
label.bottomAnchor.constraint(equalTo: superview!.bottomAnchor, constant: 0).isActive = true