需求
为UITextView添加placeholderLabel属性
解决方案
简单点,直接上代码
extension UITextView {
var placeholderLabel:UILabel?{
get{
var label:UILabel? = objc_getAssociatedObject(self, &"placeholderLabel") as? UILabel
if label == nil{
let originalText:NSAttributedString=self.attributedText
self.text=""
self.attributedText= originalText
label =UILabel()
label?.textColor=UIColor.lightGray
label?.numberOfLines=0
label?.isUserInteractionEnabled=false
//关联label属性
objc_setAssociatedObject(self, &"placeholderLabel", label, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
//KVO监听TextView各属性的变化,并更新placeholderLabel
NotificationCenter.default.addObserver(self, selector: #selector(self.updatePlaceholderLabel), name: NSNotification.Name.UITextViewTextDidChange, object: self)
let observingKeys = ["attributedText",
"bounds",
"font",
"frame",
"textAlignment",
"textContainerInset"]
for key in observingKeys {
设置监听
self.addObserver(self, forKeyPath: key, options: .new, context:nil)
}
let hooker = DeallocHooker()
//通过闭包判断TextView是否dealloc,在dealloc时移除监听
hooker.deallocHandle= {
NotificationCenter.default.removeObserver(self)
for key in observingKeys {
self.removeObserver(self, forKeyPath: key)
}
}
objc_setAssociatedObject(self, &AssociatedKeys.deallocHooker, hooker, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
returnlabel
}
}
}
其中闭包
class DeallocHooker:NSObject{
var deallocHandle:WillDealloc ?
deinit {
if deallocHandle! = nil{
deallocHandle!()
}
}
}
监听TextView的属性变化
open override func observeValue(forKeyPath keyPath:String?, of object:Any?, change: [NSKeyValueChangeKey:Any]?, context:UnsafeMutableRawPointer?) {
updatePlaceholderLabel()
}
更新placeholderLabel
@objc func updatePlaceholderLabel(){
if self.text.count > 0{
self.placeholderLabel?.removeFromSuperview()
return
}
self.insertSubview(self.placeholderLabel!, at:0)
self.placeholderLabel?.font = self.font
self.placeholderLabel?.textAlignment = self.textAlignment
let x = self.textContainer.lineFragmentPadding + self.textContainerInset.left;
let y = self.textContainerInset.top
let width = (self.bounds.width - x - self.textContainer.lineFragmentPadding - self.textContainerInset.right)
letheight =self.placeholderLabel?.sizeThatFits(CGSize(width: width, height:0)).height
self.placeholderLabel?.frame=CGRect(x: x, y: y, width: width, height: height!)
}
使用方法:
textView.placeholderLabel?.text = "请输入XXXXXXXXX"
网友评论