修改UITextField的占位文字颜色的三种层次

层次一:利用富文本

   // 描述占位文字属性
    NSMutableDictionary *dict = [NSMutableDictionary dictionary] ;
    dict[NSForegroundColorAttributeName] = [UIColor whiteColor];

    // 富文本字符串
    NSAttributedString *arrtString = [[NSAttributedString alloc] initWithString:self.placeholder attributes:dict];
    self.attributedPlaceholder = arrtString;

此种方式需要书写的代码较多,过于麻烦

方法二:利用KVC

  • 通过Debug View Hierarchy(通常所说的小面包)工具查看UITextField的图层和控件发现,UITextField内部有一个UITextFieldLabel,猜测它就是用来做占位图片的控件。

  •  

  • 通过断点调试查看UITextField的内部属性名,通过属性名获得内部私有属性placeholderLabel,然后改变颜色即可

     

  • 代码

UILabel *placeholderLabel = [self valueForKey:@"placeholderLabel"];
    placeholderLabel.textColor = [UIColor whiteColor];

此种方式代码简单不少,但是我们更希望通过点语法设置对象属性的方式那样去设置,下面看第三种方法

层次三:利用runtime

  • 思路:为UITextField增加一个分类,通过runtime的方式为UITextField增加placeholderColor属性

UITextField+placeholderColor.h 文件

@interface UITextField (placeholderColor)

@property (nonatomic, strong) UIColor *placeholderColor;

@end

UITextField+placeholderColor.m 文件

#import "UITextField+placeholderColor.h"
#import <objc/message.h>

@implementation UITextField (placeholderColor)


// placeholderColor的set方法
- (void)setPlaceholderColor:(UIColor *)placeholderColor {

    // 给UITextField添加placeholderColor属性,并设置其值为placeholderColor
    // object:保存到哪个对象中
    // key:属性名
    // value:属性值
    // policy:策略
    objc_setAssociatedObject(self, @"placeholderColor", placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    // 利用KVC方式 改变系统UITextField的占位文字的颜色
    UILabel *placeholderLabel = [self valueForKey:@"placeholderLabel"];
    placeholderLabel.textColor = placeholderColor;
}

// placeholderColor的get方法
- (UIColor *)placeholderColor {

    // 获取属性的值
   return  objc_getAssociatedObject(self, @"placeholderColor");
}

@end

这样我们就可以在工程中包含这个分类,利用点语法的方式设置占位文字的颜色,非常方便,但是在使用中会有一个bug

//  使用方式1
    self.textField.placeholder = @"jimg";
    self.textField.placeholderColor = [UIColor redColor];

//  使用方式2
    self.textField.placeholderColor = [UIColor redColor];
    self.textField.placeholder = @"jimg";

使用方式1设置可以将占位文字设置为红色,但是方式2就没有任何效果, 原因分析:

  • 原因是系统自带控件的子控件都是懒加载的,方式2情况下在设置placeholder后placeholder的label才会加载,只有在此之后设置placeholderColor才会有效。

解决办法:

  • 在设置placeholderColor的颜色时将颜色保存一份,当设置placeholder时再设置一遍placeholderColor,系统的设置placeholder方法并没有这样的功能,这时就要用到runtime将系统设置placeholder的方法换成我们自己写的方法,而且这种交换只需要执行一次,所以在类的load方法中操作。

完善后的UITextField+placeholderColor.m 文件

#import "UITextField+placeholderColor.h"
#import <objc/message.h>

static UIColor *_placeholderColor;

@implementation UITextField (placeholderColor)

// placeholderColor的set方法
- (void)setPlaceholderColor:(UIColor *)placeholderColor {

    // 给UITextField添加placeholderColor属性,并设置其值为placeholderColor
    // object:保存到哪个对象中
    // key:属性名
    // value:属性值
    // policy:策略
    objc_setAssociatedObject(self, @"placeholderColor", placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    UILabel *placeholderLabel = [self valueForKey:@"placeholderLabel"];
    placeholderLabel.textColor = placeholderColor;

    // 保存placeholderColor
    _placeholderColor = placeholderColor;
}

// placeholderColor的get方法
- (UIColor *)placeholderColor {

    // 获取属性的值
   return  objc_getAssociatedObject(self, @"placeholderColor");
}

// 将类加载到内存时调用
+(void)load {

    [super load];
    // 获取系统的setPlaceholder
    Method setPlaceholderMethod = class_getClassMethod(self, @selector(setPlaceholder:));
    // 获取自定义的setPlaceholder
    Method ymf_setPlaceholderMethod = class_getClassMethod(self, @selector(ymf_setPlaceholder:));

    // 交换方法
    method_exchangeImplementations(setPlaceholderMethod, ymf_setPlaceholderMethod);
}

// 自定义的setPlaceholder方法
- (void)ymf_setPlaceholder:(NSString *) placeholde {
    // 完成系统的操作,注意此时系统的setPlaceholder方法已经换成了ymf_setPlaceholder
    [self ymf_setPlaceholder:placeholde];

    // 再设置一边placeholderColor
    [self placeholderColor];
}

@end

至此,就可以不再关系设置顺序的问题正确设置UITextField占位文字的颜色了。

原文地址:https://www.cnblogs.com/mengfei90/p/5155060.html