UITextView+ZWPlaceHolder.m 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //
  2. // UITextView+ZWPlaceHolder.m
  3. // FinancialUnion
  4. //
  5. //
  6. //
  7. //
  8. #import "UITextView+ZWPlaceHolder.h"
  9. #import <objc/runtime.h>
  10. static const void *zw_placeHolderKey;
  11. @interface UITextView ()
  12. @property (nonatomic, readonly) UILabel *zw_placeHolderLabel;
  13. @end
  14. @implementation UITextView (ZWPlaceHolder)
  15. +(void)load{
  16. [super load];
  17. method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"layoutSubviews")),
  18. class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzling_layoutSubviews)));
  19. method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"dealloc")),
  20. class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzled_dealloc)));
  21. method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"setText:")),
  22. class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzled_setText:)));
  23. }
  24. #pragma mark - swizzled
  25. - (void)zwPlaceHolder_swizzled_dealloc {
  26. [[NSNotificationCenter defaultCenter] removeObserver:self];
  27. [self zwPlaceHolder_swizzled_dealloc];
  28. }
  29. - (void)zwPlaceHolder_swizzling_layoutSubviews {
  30. if (self.zw_placeHolder) {
  31. UIEdgeInsets textContainerInset = self.textContainerInset;
  32. CGFloat lineFragmentPadding = self.textContainer.lineFragmentPadding;
  33. CGFloat x = lineFragmentPadding + textContainerInset.left + self.layer.borderWidth;
  34. CGFloat y = textContainerInset.top + self.layer.borderWidth;
  35. CGFloat width = CGRectGetWidth(self.bounds) - x - textContainerInset.right - 2*self.layer.borderWidth;
  36. CGFloat height = [self.zw_placeHolderLabel sizeThatFits:CGSizeMake(width, 0)].height;
  37. self.zw_placeHolderLabel.frame = CGRectMake(x, y, width, height);
  38. }
  39. [self zwPlaceHolder_swizzling_layoutSubviews];
  40. }
  41. - (void)zwPlaceHolder_swizzled_setText:(NSString *)text{
  42. [self zwPlaceHolder_swizzled_setText:text];
  43. if (self.zw_placeHolder) {
  44. [self updatePlaceHolder];
  45. }
  46. }
  47. #pragma mark - associated
  48. -(NSString *)zw_placeHolder{
  49. return objc_getAssociatedObject(self, &zw_placeHolderKey);
  50. }
  51. -(void)setZw_placeHolder:(NSString *)zw_placeHolder{
  52. objc_setAssociatedObject(self, &zw_placeHolderKey, zw_placeHolder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  53. [self updatePlaceHolder];
  54. }
  55. -(UIColor *)zw_placeHolderColor{
  56. return self.zw_placeHolderLabel.textColor;
  57. }
  58. -(void)setZw_placeHolderColor:(UIColor *)zw_placeHolderColor{
  59. self.zw_placeHolderLabel.textColor = zw_placeHolderColor;
  60. }
  61. -(NSString *)placeholder{
  62. return self.zw_placeHolder;
  63. }
  64. -(void)setPlaceholder:(NSString *)placeholder{
  65. self.zw_placeHolder = placeholder;
  66. }
  67. #pragma mark - update
  68. - (void)updatePlaceHolder{
  69. if (self.text.length) {
  70. [self.zw_placeHolderLabel removeFromSuperview];
  71. return;
  72. }
  73. self.zw_placeHolderLabel.font = self.font?self.font:self.cacutDefaultFont;
  74. self.zw_placeHolderLabel.textAlignment = self.textAlignment;
  75. self.zw_placeHolderLabel.text = self.zw_placeHolder;
  76. [self insertSubview:self.zw_placeHolderLabel atIndex:0];
  77. }
  78. #pragma mark - lazzing
  79. -(UILabel *)zw_placeHolderLabel{
  80. UILabel *placeHolderLab = objc_getAssociatedObject(self, @selector(zw_placeHolderLabel));
  81. if (!placeHolderLab) {
  82. placeHolderLab = [[UILabel alloc] init];
  83. placeHolderLab.numberOfLines = 0;
  84. placeHolderLab.textColor = [UIColor lightGrayColor];
  85. objc_setAssociatedObject(self, @selector(zw_placeHolderLabel), placeHolderLab, OBJC_ASSOCIATION_RETAIN);
  86. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceHolder) name:UITextViewTextDidChangeNotification object:self];
  87. }
  88. return placeHolderLab;
  89. }
  90. - (UIFont *)cacutDefaultFont{
  91. static UIFont *font = nil;
  92. static dispatch_once_t onceToken;
  93. dispatch_once(&onceToken, ^{
  94. UITextView *textview = [[UITextView alloc] init];
  95. textview.text = @" ";
  96. font = textview.font;
  97. });
  98. return font;
  99. }
  100. @end