UITextView+Placeholder

UITextView 扩展 Placeholder

Posted by BY on August 8, 2019

Swift UITextView 扩展 Placeholder


import UIKit

fileprivate var kTextViewPlaceholderLabel : Int = 0x2019_00
fileprivate var kTextViewPlaceholder      : Int = 0x2019_01
fileprivate var kTextViewPlaceholderColor : Int = 0x2019_02
fileprivate var kTextViewPlaceholderFont  : Int = 0x2019_03
fileprivate var kTextViewPlaceholderKeys  : Int = 0x2019_04

extension UITextView {

    /// 占位符
    var x_placeholder: String {
        get {
            if let placeholder = objc_getAssociatedObject(self, &kTextViewPlaceholder) as? String {
                return placeholder
            } else {
                return ""
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholder, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.text = newValue
        }
    }

    /// 占位符颜色
    var x_placeholderColor: UIColor {
        get {
            if let placeholderColor = objc_getAssociatedObject(self, &kTextViewPlaceholderColor) as? UIColor {
                return placeholderColor
            } else {
                return UIColor.subTitleColor
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderColor, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.textColor = newValue
        }
    }

    /// 占位符字体
    var x_placeholderFont: UIFont {
        get {
            if let placeholderFont = objc_getAssociatedObject(self, &kTextViewPlaceholderColor) as? UIFont {
                return placeholderFont
            } else {
                return UIFont.systemFont(ofSize: 12)
            }
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderColor, newValue, .OBJC_ASSOCIATION_RETAIN)
            x_placeholderLabel.font = newValue
        }
    }

    /// 占位符 标签
    @IBInspectable var x_placeholderLabel: UILabel {
        get {
            var _placeholderLabel = UILabel(font: self.font ?? UIFont.systemFont(ofSize: 12), color: .subTitleColor, alignment: .left)
            if let label = objc_getAssociatedObject(self, &kTextViewPlaceholderLabel) as? UILabel {
                _placeholderLabel = label
            } else {
                objc_setAssociatedObject(self, &kTextViewPlaceholderLabel, _placeholderLabel, .OBJC_ASSOCIATION_RETAIN)
            }

            addPlaceholderLabelToSuperView(label: _placeholderLabel)

            return _placeholderLabel
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderLabel, newValue, .OBJC_ASSOCIATION_RETAIN)
            addPlaceholderLabelToSuperView(label: newValue)
        }
    }

    /// 是否需要添加占位符到父视图
    fileprivate var x_placeHolderNeedAddToSuperView: Bool {
        get {
            if let isAdded = objc_getAssociatedObject(self, &kTextViewPlaceholderKeys) as? Bool {
                return isAdded
            }
            return true
        }
        set {
            objc_setAssociatedObject(self, &kTextViewPlaceholderKeys, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    /// 添加占位符到父视图
    ///
    /// - Parameter label: 占位符 标签
    fileprivate func addPlaceholderLabelToSuperView(label: UILabel) {

        guard x_placeHolderNeedAddToSuperView else { return }
        x_placeHolderNeedAddToSuperView = false

        NotificationCenter.default.addObserver(self, selector: #selector(x_textChange(noti:)), name: UITextView.textDidChangeNotification, object: nil)

        addSubview(label)
        label.snp.makeConstraints { (make) in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 7, left: 2, bottom: 0, right: 0))
        }
    }

    /// 编辑事件
    @objc fileprivate func x_textChange(noti: NSNotification) {
        let isEmpty = text.isEmpty
        print("text:\(String(describing: text))\nisEmpty:\(isEmpty)")
        x_placeholderLabel.text = isEmpty ? x_placeholder : ""
        x_placeholderLabel.isHidden = !isEmpty
    }
}