UITTextViewにplacceholderをどうやって拡張するか教えてください.


UICTextViewをどうやって拡張してplacceholder機能を追加しますか?
私達の需要はplacholder機能を追加することです.
スキームの検討:
  • は、UITextViewを継承することによって
  • である.
  • は、UITextViewを拡張することによって
  • である.
    解析:方案1は継承方式を使って実現するのがもっと簡単ですが、使うのがそんなに便利ではありません.案2は拡張方式を使用しており、実現は前者よりやや複雑であるが、外部での使用はより簡単である.
    方案の位置付け:拡張方式を採用して、きわめて簡単な風格を参考にします.
    Tip:いわゆる極簡、つまり対外インターフェースは最も簡単で、内部に対してとても複雑なことができます.
    拡張子ファイル
    #import <UIKit/UIKit.h>
    
    /** * @author huangyibiao * *  UITextView  placeholder * * @note   ,        ,     placeholder ,     Text  ,        *      :      ,  text,   holder */
    @interface UITextView (HDFTextView)
    
    /** *       */
    @property (nonatomic, copy)   NSString *hdf_placeholder;
    
    /** *            */
    @property (nonatomic, strong) UIColor *hdf_placeholderColor;
    
    /** *          */
    @property (nonatomic, strong) UIFont  *hdf_placeholderFont;
    
    /** *         */
    @property (nonatomic, strong, readonly) UILabel *hdf_placeholderLabel;
    
    
    @end
    シシシシ萼説明:ヘッド文書ではhdf_だけ公開する必要があります.plceholderLabel属性は実現できますが、hdf_を公開しました.plceholderLabelの直接属性は個人の習慣によって使用できます.拡張は属性を拡張することはできませんが、ここでは属性の形を書きました.実はgetter/setter方式を利用してAPIを書き直しました.内部では動的運転時のメカニズムを使用して疑似属性を拡張する機能を完成します.
    実現ファイル
    #import "UITextView+HDFTextView.h"
    
    static const void *s_hdfTextViewPlaceholderLabelKey = "s_hdfTextViewPlaceholderLabelKey";
    static const void *s_hdfTextViewPlaceholderTextKey = "s_hdfTextViewPlaceholderTextKey";
    
    @interface UIApplication (HDFTextViewHolder)
    
    @end
    
    @implementation UIApplication (HDFTextViewHolder)
    
    - (void)hdf_placehoderTextChange:(NSNotification *)nofitication {
      if (kIsIOS7OrLater) {
        return;
      }
      UITextView *textView = nofitication.object;
      if ([textView isKindOfClass:[UITextView class]]) {
        if (!kIsEmptyString(textView.text)) {
          textView.hdf_placeholderLabel.text = @"";
        } else {
          textView.hdf_placeholderLabel.text = textView.hdf_placeholder;
        }
      }
    }
    
    @end
    
    @interface UITextView (HDFPlaceholderTextView)
    
    @property (nonatomic, strong) UILabel *placeholderLabel;
    
    @end
    
    @implementation UITextView (HDFPlaceholderTextView)
    
    - (void)setPlaceholderLabel:(UILabel *)placeholderLabel {
      objc_setAssociatedObject(self,
                               s_hdfTextViewPlaceholderLabelKey,
                               placeholderLabel,
                               OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UILabel *)placeholderLabel {
      UILabel *label = objc_getAssociatedObject(self, s_hdfTextViewPlaceholderLabelKey);
    
      if (label == nil || ![label isKindOfClass:[UILabel class]]) {
        label = [[UILabel alloc] init];
        label.textAlignment = NSTextAlignmentLeft;
        label.font = self.font;
        label.backgroundColor = [UIColor clearColor];
        label.textColor = kHolderTipColor;
        [self addSubview:label];
    
        kWeakObject(self);
        self.placeholderLabel = label;
        CGFloat left = kIsIOS7OrLater ? 5 : 7;
        [label mas_makeConstraints:^(MASConstraintMaker *make) {
          make.edges.mas_equalTo(weakObject).insets(UIEdgeInsetsMake(7.5, left, 0, 0));
        }];
        label.enabled = NO;
    
        [kNotificationCenter addObserver:kIsIOS7OrLater ? self : [UIApplication sharedApplication]
                                selector:@selector(hdf_placehoderTextChange:)
                                    name:UITextViewTextDidChangeNotification
                                  object:nil];
      }
    
      return label;
    }
    
    @end
    
    @implementation UITextView (HDFTextView)
    
    - (void)hdf_placehoderTextChange:(NSNotification *)notification {
      if (kIsIOS7OrLater) {
        if (!kIsEmptyString(self.text)) {
          self.placeholderLabel.text = @"";
        } else {
          self.placeholderLabel.text = self.hdf_placeholder;
        }
      }
    }
    
    - (UILabel *)hdf_placeholderLabel {
      return self.placeholderLabel;
    }
    
    - (void)setHdf_placeholder:(NSString *)hdf_placeholder {
      if (kIsEmptyString(hdf_placeholder)) {
        objc_setAssociatedObject(self, s_hdfTextViewPlaceholderLabelKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        [self.placeholderLabel removeFromSuperview];
        return;
      }
    
      objc_setAssociatedObject(self,
                               s_hdfTextViewPlaceholderTextKey,
                               hdf_placeholder,
                               OBJC_ASSOCIATION_COPY_NONATOMIC);
    
      if (!kIsEmptyString(self.text)) {
        self.placeholderLabel.text = @"";
      } else {
        self.placeholderLabel.text = hdf_placeholder;
      }
    }
    
    - (NSString *)hdf_placeholder {
      return objc_getAssociatedObject(self, s_hdfTextViewPlaceholderTextKey);
    }
    
    - (void)setHdf_placeholderColor:(UIColor *)hdf_placeholderColor {
      self.placeholderLabel.textColor = hdf_placeholderColor;
    }
    
    - (UIColor *)hdf_placeholderColor {
      return self.placeholderLabel.textColor;
    }
    
    - (void)setHdf_placeholderFont:(UIFont *)hdf_placeholderFont {
      self.placeholderLabel.font = hdf_placeholderFont;
    }
    
    - (UIFont *)hdf_placeholderFont {
      return self.placeholderLabel.font;
    }
    
    @end
    説明:ここの実装ファイルは、実行時のメカニズムを使用しています.ここでテキスト変更の傍受は、自分とUAPplicationに任せました.IOS 6.0に対応するために、自分に渡してはいけません.崩壊しますので、UApplication単体の対象に移管して管理します.
    ここではMasonaryという自動レイアウトの三方倉庫を使っています.このplacholderlabelは自動的にuitextviewの大きさによって変化します.コードにはIOSシステムが使用されています.空のコードかどうかを判断します.ここには書きません.自分で代わります.
    次は使います.使いやすいです.
      self.remarkView.text = @"  ,    ";
      self.remarkView.hdf_placeholder = @"    ...";
    備考:需要の中でtextviewにplacceholderを追加する必要がある時、ネット上のはすべて継承の方式で、まだ多くのところを修正しなければならなくて、これはいけないので、私はやっとこの問題を提出して、そして自分の解決案を作り出しました.皆さんに役に立つなら、安心して持って行って使ってください.
    対応IO S 6.0およびそれ以上のバージョン