提醒
關于本文的修改方法是否屬于修改私有api的問題,我已經確定不屬于。我的APP里面用了這個方法,提交審核順利通過。所以大家可以愉快放心的使用了。
前言
最近一致比較忙,在做一個需求很多的功能。所以很少來看,趁著早上來到閑一會,把前幾天用到的小技巧告訴大家。首先我想說的是我給的是一種思路,怎么解決此類需求的思路,不是我寫個uialert大家就知道這uialert。工作猶如逆水行舟,不進則退。共勉。
Demo地址
正文
UIDatePicker
UIDatePicker大家應該不陌生吧,我們在項目中經常使用。一般大家都是需求這樣的:
但是有的時候吧,ui抽風或者需求下雨我們可能需要這樣的:
沒辦法,誰讓你是苦逼的程序員,所以你開始征服之路,經過你寫出來是這樣的:
徹底無語了,想唱一首歌:時間都去哪里去了。于是你去找UIDatePicker的各種屬性,結果發現并沒有改變字體顏色的屬性,怎么辦,需求在催,ui在催......(此處省略一萬字)。現在不用怕,鹵煮給你一個簡單的思路方法解決它。
首先,我們想想蘋果設計這一個控件,不可能不給他的普通的屬性方法,改變字體顏色,大小是最普通的屬性了吧。那為什么找不到呢,只有一個可能,就像我們提交appstore一樣,我們隱藏了。那么,知道了原因就好了我們去找路徑解決。閑雜i 我們怎么拿到隱藏的屬性呢,不禁想到了runtimer。不管你之前有沒有使用過這個東西,以下的你看起來應該不會有障礙。
來,先讓我們知道兩個東西:
1,objc_property_t 屬性的定義,說白了就是這種形式:
@property(nonatomic,strong)UILabel *cdLabel;
2,Ivar 成員變量的定義,說白了就是這種形式:
{
YFDatePicker *picker;
UIAlertAction *alertOk;
UIAlertAction *alertCancel;
UIAlertController *alert;
}
知道這兩種的不同,以下的就好進行了。開干:
首先咱們自定義個UIDatePicker,用于改變字體的顏色:
#import <UIKit/UIKit.h>
@interface YFDatePicker : UIDatePicker
- (void)setTextColor;//字體顏色
@end
其次,.m把構造方法寫一下:
- (instancetype)init{
self = [super init];
if (self) {
[self setPicker];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self setPicker];
}
return self;
}
- (void)setPicker{
self.backgroundColor = [UIColor blackColor];
}
然后重點來了:導入runtimer
#import <objc/runtime.h>
獲取到所有的屬性
//獲取所有的屬性,去查看有沒有對應的屬性
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([UIDatePicker class], &count);
for(int i = 0;i < count;i ++){
//獲得每一個屬性
objc_property_t property = propertys[i];
//獲得屬性對應的nsstring
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
//輸出打印看對應的屬性
NSLog(@"propertyname = %@",propertyName);
}
我一句一句翻譯一下:
//獲取所有的屬性,去查看有沒有對應的屬性
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([UIDatePicker class], &count);
這個是獲取一個數組,一個里面放了對應的屬性的數組。class_copyPropertyList這個方法是獲取后面對應的UIDatePicker的所有的屬性,后面的count是得到這個數組的量。這就是一個方法,獲取ivar,method都是對應的class_copy + 名字。
//獲得每一個屬性
objc_property_t property = propertys[i];
//獲得屬性對應的nsstring
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
從這個數組里面一一拿出來每一個屬性,然后因為這個屬性是char類型的,我們轉換為字符串類型去做對應的操作。
,好了,我們運行一下輸出所有的property,看看有沒有我們需要的屬性:
結果我們發現有textColor這個屬性,雞凍呀,看著這個屬性就想日破天了。
然后我們知道有這個屬性,怎么用它呢,這時候kvc的好處來了。直接kvc賦值:
- (void)setTextColor{
//獲取所有的屬性,去查看有沒有對應的屬性
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([UIDatePicker class], &count);
for(int i = 0;i < count;i ++){
//獲得每一個屬性
objc_property_t property = propertys[i];
//獲得屬性對應的nsstring
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
//輸出打印看對應的屬性
NSLog(@"propertyname = %@",propertyName);
if ([propertyName isEqualToString:@"textColor"]) {
[self setValue:[UIColor whiteColor] forKey:propertyName];
}
}
}
然后我們去看一下運行效果:
終于搞定啦。
當然你也可以直接這樣來:
[self setValue:[UIColor whiteColor] forKey:@"textColor"];
但是怎么說呢,你如果不獲取他的所有屬性你是怎么知道的這個屬性呢。當然,你之前獲取過知道了直接用確實快多了哈。看個人啦!!!
UIAlert
再來看一個UIAlert的改變。
正常的我們需要的是這樣的:
但是有的時候,**的需求(我會不會被某些需求人士狂揍)會需要這樣的:
然后我寫了這些:
alert = [UIAlertController alertControllerWithTitle:@"彈出框" message:@"你看我的顏色" preferredStyle:UIAlertControllerStyleAlert];
alertOk = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"哎呦,確定了");
}];
[alert addAction:alertOk];
alertCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"呦西,取消");
}];
[alert addAction:alertCancel];
[self presentViewController:alert animated:YES completion:nil];
接著,沒有思路了,去查看了UIAlertController的API,就那幾個屬性和方法,一只手指頭都能數的出來,怎么辦。自己寫一個,但是趕腳又做的效果沒有系統的好。不用怕,鹵煮來了。
老樣子我們先去獲取屬性看看:
//首先獲得對應的屬性
unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([UIAlertAction class], &count);
for(int i = 0;i < count;i ++){
objc_property_t property = propertys[i];
//獲得屬性名對應字符串
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
NSLog(@"uialertion.property = %@",propertyName);
}
結果我們發現輸出結果:
我擦嘞,沒有改變字體的屬性,這怎么辦,難道蘋果真的沒有,不可能呀......不要著急,我們還沒有獲取ivar看看呢,說不定就在ivar這:
//獲得成員變量
Ivar *ivars = class_copyIvarList([UIAlertAction class], &count);
for(int i =0;i < count;i ++){
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
NSLog(@"uialertion.ivarName = %@",ivarName);
}
控制臺輸出:
果然呀,上帝在關上窗戶的時候,往往不會關緊。我們找到了對應的屬性,現在就是賦值了
//獲得成員變量
Ivar *ivars = class_copyIvarList([UIAlertAction class], &count);
for(int i =0;i < count;i ++){
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
NSLog(@"uialertion.ivarName = %@",ivarName);
if ([ivarName isEqualToString:@"_titleTextColor"]) {
[alertOk setValue:[UIColor blueColor] forKey:@"titleTextColor"];
[alertCancel setValue:[UIColor purpleColor] forKey:@"titleTextColor"];
}
}
我們現在是改變了按鈕的對應的字體顏色,現在我們去改變內容的字體屬性:
/********************************************************************/
//改變顯示提示字體顏色
objc_property_t *propertyss = class_copyPropertyList([UIAlertController class], &count);
for(int i = 0;i < count;i ++){
objc_property_t propertys = propertyss[i];
//獲得屬性名對應字符串
NSString *propertyNames = [NSString stringWithCString:property_getName(propertys) encoding:NSUTF8StringEncoding];
NSLog(@"UIAlertController.property = %@",propertyNames);
}
Ivar *ivarss = class_copyIvarList([UIAlertController class], &count);
for(int i =0;i < count;i ++){
Ivar ivars = ivarss[i];
NSString *ivarNames = [NSString stringWithCString:ivar_getName(ivars) encoding:NSUTF8StringEncoding];
NSLog(@"UIAlertController.ivarName = %@",ivarNames);
if ([ivarNames isEqualToString:@"_attributedTitle"]) {
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc]initWithString:@"我是標題" attributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
[alert setValue:attr forKey:@"attributedTitle"];
}
if ([ivarNames isEqualToString:@"_attributedMessage"]) {
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc]initWithString:@"土豆哪里去挖,土豆山溝里挖" attributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:1.0 green:0.5 blue:0.0 alpha:1.0],NSFontAttributeName:[UIFont systemFontOfSize:25]}];
[alert setValue:attr forKey:@"attributedMessage"];
}
}
你會發現運行結果控制臺輸出:
并沒有說textcolor這一類的屬性,但是發現了兩個野生的_attributedTitle,_attributedMessage。看著就是對應的title和message的字體。當然如果你不熟悉NSAttributedString的話,可以看一下我之前有一篇專門解釋這個屬性的。
得到這兩個我們去改變就很輕松了,直接賦值就ok了。
結語
好了,好了,差不多得了,萬惡的后臺雞巴又在催我了。我要去碼字了,UIActionSheet的字體試著去做一下,還是那句話: