利用Runtime修改UIdatePicker的字体颜色

2024-09-02 16:08

本文主要是介绍利用Runtime修改UIdatePicker的字体颜色,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 用过苹果原生UIdatePicker的Ios开发者都知道,UIdatePicker这个时间选择器的字体颜色默认的是黑色,并且官方API并没有提供可以修改字体颜色的API。如下:
UIDatePicker *picker = [[UIDatePicker alloc] init];picker.datePickerMode = UIDatePickerModeDate;picker.maximumDate = [NSDate dateWithTimeIntervalSince1970:0];picker.minimumDate = [NSDate dateWithTimeIntervalSinceNow:10000];[picker setDate:[NSDate date]];

通过runtime处理之后的结果

做到上面这个效果,我主要进行了如下步骤:

  1. 利用通过遍历UIDatePicker类的所有属性,包括写在.m文件中看不到的属性。
  2. 找到苹果用于修改字体颜色的属性使用rumtime动态修改。
unsigned int outCount;int i;objc_property_t *pProperty = class_copyPropertyList([UIDatePicker class], &outCount);for (i = outCount -1; i >= 0; i--){// 循环获取属性的名字   property_getName函数返回一个属性的名称NSString *getPropertyName = [NSString stringWithCString:property_getName(pProperty[i]) encoding:NSUTF8StringEncoding];NSString *getPropertyNameString = [NSString stringWithCString:property_getAttributes(pProperty[i]) encoding:NSUTF8StringEncoding];if([getPropertyName isEqualToString:@"textColor"]){[picker setValue:[UIColor whiteColor] forKey:@"textColor"];}NSLog(@"%@====%@",getPropertyNameString,getPropertyName);}

以上代码中pProperty返回的是一个所有属性的数组,通过循环遍历我发现@”textColor”这个属性应该就是我想要的属性,然后通过setValue赋值白色,最后就做到了上图的结果。

或许说干过两年ios开发的都知道这个东西,但是笔者更想表达的还是这种分析问题和处理问题并最终解决问题的思想,当我们修改系统原生控件遇到瓶颈的时候可以采用这种方法来学习这个控件更多的特性

如果你觉得不过瘾?那就继续吧,更刺激的还在后面呢~

  • 本来这个地方做好之后,结果测试测出一个非常奇葩的bug,就是UIDatepicker在当天的字体仍然是黑色。
    -如下图
    看见了么
    看到了么,因为我在写这篇文章的时候是九月一号,所以九月一号的字体还是以前的黑色,比如说我动态改变系统日期为九月二号,它也会自动变成九月二号的字体是黑色,由于UI设计的是背景黑色,所以这里根本就看不清,严重影响产品体验。

  • 通过一系列的纠结,我最后发现,如果UIDatepicker设置了最大时间(maxDate)和最小时间(minDate)就会这样,如果不设置就不出现这种情况,但是需求要限制最大时间和最小时间。
    在这个解决的过程中,我试过了遍历属性还有查看官方API都找不到任何资料,甚至都想不通苹果内部是怎么处理的这么牛逼的。
    实在没办法,我到处百度还是没进展,最后我终于在国外的网站找老外解决了这个问题(老外为啥比国人要牛逼呢?)
    解决这个问题的核心代码如下:

SEL selector = NSSelectorFromString(@"setHighlightsToday:");NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDatePicker instanceMethodSignatureForSelector:selector]];BOOL no = NO;[invocation setSelector:selector];[invocation setArgument:&no atIndex:2];[invocation invokeWithTarget:picker];

通过这个代码我不断的逆向推理其实现原理,并且各种百度查找NSInvocation的相关资料。
最后让我逐步来解析一下每一行代码的意思:

  1. SEL selector =NSSelectorFromString(@”setHighlightsToday:”);
    通过Runtime的NSSelectorFromString利用字符串获取方法@”setHighlightsToday:”(注意,看这个方法名就是今天的高亮显示开关,注意字符串后面的冒号,表示这个方法是有参数的)

  2. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDatePicker instanceMethodSignatureForSelector:selector]];
    用这个SEL创建UIdatepicker类的NSMethodSignature来创建一个NSInvocation。

  3. BOOL no = NO;
    [invocation setSelector:selector];
    [invocation setArgument:&no atIndex:2];
    [invocation invokeWithTarget:picker];
    给invocation设置参数,设置target,并且动态调用设置参数NO(苹果默认YES并且不开放)
    其实NSInvocation也是Runtime的一种方式。
    注意[invocation setArgument:&no atIndex:2];这个2是怎么来的,因为setArgument中第一个参数的类picker,第二个参数是SEL,所以我们自己的参数最小的数字就是2,也就是这个方法的第一个参数

最后问题彻底解决了,晒张截图求真相:

虽然问题是最终解决了,但是假如下次我们又遇到这种类似的问题应该怎么办呢?难道又要焦头烂额的到处寻求援助么?程序员的上进心和求学心哪里去了?

最后笔者花了一到两天的时间一直思考这个问题,并最终通过分析老外的解决方式逆向找到解决的具体原理

前面说过,可以通过NSString *getPropertyName = [NSString stringWithCString:property_getName(pProperty[i]) encoding:NSUTF8StringEncoding];来获取一个类所有的属性,最后我在Runtime的API中发现,也可以获取一个类所有的方法(有兴趣的可以去了解一下IMP指针)。

unsigned int outCount;int i;Method *method = class_copyMethodList([UIDatePicker class],&outCount);

也就是说,利用Rumtime遍历某个类的所有属性和所有的方法,苹果的API限制在我们面前形同虚设,可以解决更多的一些原生API不开放的东西,其实这里也可以自己重写,不过相当麻烦,而且会有复杂的内存问题,所以还是直接用Runtime绕过苹果限制修改原生控件简单的多

其实runtime本身的东西很少,更多的是一些概念性的东西,有兴趣的也可以去了解一下runtime,本文主要讲的是一种利用runtime去解决实际问题的思维方式。

欢迎大家转载学习并且指出笔者不到之处,转载请注明出处哈!

这篇关于利用Runtime修改UIdatePicker的字体颜色的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130428

相关文章

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

MySQL修改密码的四种实现方式

《MySQL修改密码的四种实现方式》文章主要介绍了如何使用命令行工具修改MySQL密码,包括使用`setpassword`命令和`mysqladmin`命令,此外,还详细描述了忘记密码时的处理方法,包... 目录mysql修改密码四种方式一、set password命令二、使用mysqladmin三、修改u

使用Python在Excel中插入、修改、提取和删除超链接

《使用Python在Excel中插入、修改、提取和删除超链接》超链接是Excel中的常用功能,通过点击超链接可以快速跳转到外部网站、本地文件或工作表中的特定单元格,有效提升数据访问的效率和用户体验,这... 目录引言使用工具python在Excel中插入超链接Python修改Excel中的超链接Python

电脑没有仿宋GB2312字体怎么办? 仿宋GB2312字体下载安装及调出来的教程

《电脑没有仿宋GB2312字体怎么办?仿宋GB2312字体下载安装及调出来的教程》仿宋字体gb2312作为一种经典且常用的字体,广泛应用于各种场合,如何在计算机中调出仿宋字体gb2312?本文将为您... 仿宋_GB2312是公文标准字体之一,仿China编程宋是字体名称,GB2312是字php符编码标准名称(简

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

python修改字符串值的三种方法

《python修改字符串值的三种方法》本文主要介绍了python修改字符串值的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录第一种方法:第二种方法:第三种方法:在python中,字符串对象是不可变类型,所以我们没办法直接

Mysql8.0修改配置文件my.ini的坑及解决

《Mysql8.0修改配置文件my.ini的坑及解决》使用记事本直接编辑my.ini文件保存后,可能会导致MySQL无法启动,因为MySQL会以ANSI编码读取该文件,解决方法是使用Notepad++... 目录Myhttp://www.chinasem.cnsql8.0修改配置文件my.ini的坑出现的问题

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991

android系统源码12 修改默认桌面壁纸--SRO方式

1、aosp12修改默认桌面壁纸 代码路径 :frameworks\base\core\res\res\drawable-nodpi 替换成自己的图片即可,不过需要覆盖所有目录下的图片。 由于是静态修改,则需要make一下,重新编译。 2、方法二Overlay方式 由于上述方法有很大缺点,修改多了之后容易遗忘自己修改哪些文件,为此我们采用另外一种方法,使用Overlay方式。