我的修改UIDatePicker,UIAlert等字體屬性的方法?不,是你的

提醒

關于本文的修改方法是否屬于修改私有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的字體試著去做一下,還是那句話:

逆水行舟,只能進,不能退.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 摘自: http://www.cocoachina.com/ios/20150803/12872.html 說明...
    program袁閱讀 885評論 1 3
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,075評論 25 708
  • 這篇日記寫于2010年11月,剛結束了一段感情,心情低落,和朋友去寺廟游玩,回來后記錄。翌年,邂逅了一個美麗的湘西...
    不知樹閱讀 527評論 0 1
  • 嘩啦啦的流水,叮咚叮咚的騾鈴,云霧繚繞的山谷,在期盼中新的一天又開始了... 早餐是昨夜摸黑在小賣部,尋得的...
    曉行家閱讀 314評論 6 5
  • 平日里的悵然若失, 微醉中的如花似夢, 骨子里的尋尋覓覓, 對酒當歌的夜晚, 時而冰天雪地, 時而春暖花開, 愿,...
    小軒未名閱讀 129評論 0 0