层次一:利用富文本
// 描述占位文字属性
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占位文字的颜色了。