利用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

相关文章

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

Linux修改pip临时目录方法的详解

《Linux修改pip临时目录方法的详解》在Linux系统中,pip在安装Python包时会使用临时目录(TMPDIR),但默认的临时目录可能会受到存储空间不足或权限问题的影响,所以本文将详细介绍如何... 目录引言一、为什么要修改 pip 的临时目录?1. 解决存储空间不足的问题2. 解决权限问题3. 提

Linux文件名修改方法大全

《Linux文件名修改方法大全》在Linux系统中,文件名修改是一个常见且重要的操作,文件名修改可以更好地管理文件和文件夹,使其更具可读性和有序性,本文将介绍三种在Linux系统下常用的文件名修改方法... 目录一、引言二、使用mv命令修改文件名三、使用rename命令修改文件名四、mv命令和rename命

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

Linux下修改hostname的三种实现方式

《Linux下修改hostname的三种实现方式》:本文主要介绍Linux下修改hostname的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下修改ho编程stname三种方式方法1:修改配置文件方法2:hFvEWEostnamectl命

Git如何修改已提交人的用户名和邮箱

《Git如何修改已提交人的用户名和邮箱》文章介绍了如何修改Git已提交人的用户名和邮箱,包括注意事项和具体步骤,确保操作正确无误... 目录git修改已提交人的用户名和邮箱前言第一步第二步总结git修改已提交人的用户名和邮箱前言需注意以下两点内容:需要在顶层目录下(php就是 .git 文件夹所在的目

Python批量调整Word文档中的字体、段落间距及格式

《Python批量调整Word文档中的字体、段落间距及格式》这篇文章主要为大家详细介绍了如何使用Python的docx库来批量处理Word文档,包括设置首行缩进、字体、字号、行间距、段落对齐方式等,需... 目录关键代码一级标题设置  正文设置完整代码运行结果最近关于批处理格式的问题我查了很多资料,但是都没

基于Python实现一个PDF特殊字体提取工具

《基于Python实现一个PDF特殊字体提取工具》在PDF文档处理场景中,我们常常需要针对特定格式的文本内容进行提取分析,本文介绍的PDF特殊字体提取器是一款基于Python开发的桌面应用程序感兴趣的... 目录一、应用背景与功能概述二、技术架构与核心组件2.1 技术选型2.2 系统架构三、核心功能实现解析