iOS开发运行时机制介绍

iOS开发有很多很神奇的东西,虽然有时候用到的不是很多,或者说目前还没用到,但是作为一名iOS工程师,了解和掌握这些东西是必不可少的。下面就介绍一位重量级的选手--iOS的黑魔法----运行时机制。

何为运行时?下面两句话就是对其最基础也最准确的概括介绍:

 运行时(Runtime): 

 * 苹果官方一套C语言库

 * 能做很多底层操作(比如访问隐藏的一些成员变量\成员方法....)

其实作为一名开发工程师,已经开发了一年多了,用到运行时机制的情况也是屈指可数,但是觉得这个知识点依然还是很重要,面试的时候也是很受青睐的一个问题,下面先简单的介绍一下这个神奇的功能。目前对于运行时的探索分为两个方面:

一:利用运行时获得某些对象或者类的成员变量和属性

乍一看会觉得不就是获取一些成员变量和属性嘛,直接点进去头文件看一下不就行了嘛?至于牵涉到这么复杂的问题吗?请注意,这里说的的成员变量,更加准确的描述是一些私有的成员变量,这里就可以想象到它的价值了吧!没错,自定义控件!

利用运行时自定义控件的情景用法:

自定义控件的情景自然无需赘述,那就是系统自带的控件难以满足我们的需求,所以要自定义控件。下面主要介绍一下用法,介绍用法通过一个例子来说明吧。开发过程中,有木有发现UITextField竟然没有暴露一个属性来设置起占位文字的颜色,对于一个这么常用的控件,这么常见得需求都没有暴露出来,真想不通啊。对于产品狗的这种需求,自然就得自定义UITextField了,实现起来思路有很多,但是最简单的一种就是这里要介绍的----运行时机制。我们可以通过运行时机制打印出来UITextField的成员变量,来看看有没有符合条件的,直接尝试对这个成员变量进行设置可谓一步到位,无需多余的其他复杂的想法。说干就干,

+ (void)getProperties
{
    unsigned int count = 0;
    
    objc_property_t *properties = class_copyPropertyList([UITextField class], &count);
    
    for (int i = 0; i<count; i++) {
        // 取出属性
        objc_property_t property = properties[i];
        
        // 打印属性名字
        XMGLog(@"%s   <---->   %s", property_getName(property), property_getAttributes(property));
    }
    
    free(properties);
}

+ (void)getIvars
{
    unsigned int count = 0;
    
    // 拷贝出所有的成员变量列表
    Ivar *ivars = class_copyIvarList([UITextField class], &count);
    
    for (int i = 0; i<count; i++) {
        // 取出成员变量
        //        Ivar ivar = *(ivars + i);
        Ivar ivar = ivars[i];
        
        // 打印成员变量名字
        XMGLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
    }
    
    // 释放
    free(ivars);
}<span style="color:#703daa;">
</span>
通过上面的运行时提供的一些方法,就可以轻松获得一些控件隐藏的成员变量和属性,通过上面的打印可以得到很多,稍微筛选一下就会看到一个很可疑的成员变量---- _placeholderLabel,没错,就是它,稍加验证就会发现,完全可行,那岂不是很轻松,直接通过KVC进行设置即可:

[selfsetValue:self.textColorforKeyPath:_placeholderLabel.textColor];

PS:KVC在开发中是很常用也很实用的一个方法,务必掌握,另外,它很常用的一种方法通过点语法进行递归设置。

轻松搞定,不用再考虑其他的太复杂的想法,简单明了!!!

二:利用运行时交换某个对象或类的某些方法----Method Swizzile(iOS黑魔法)

或许你会说为什么要交换呢?直接需要哪个调用哪个方法不就行了吗,搞那么费劲干什么?不错,对于一些暴露出来的或者自定义的类你可以通过直接调用的方式来做到,但是对于系统自己的方法,你怎么解决?假如有这么一个需求:现在有几十个控制器,我想看一下到底是哪个控制器出现了内存泄漏,也就是没有被释放掉?那你会怎么解决?首先会想到重写dealloc方法不就行了,打印输出一下,看看谁没有调用,对于这几十个控制器你要分别重写吗?显然这是比较低效的,此时可以使用运行时的又一法宝----方法交换。我们可以给viewController增加一个分类,如下



PS:1.第13行,load方法比viewDidLoad方法还要早执行,在控制器载入内存的时候就会调用这个方法
2.第15行,对于ARC 环境,@selector不允许传进来dealloc方法,我们可以通过NSSelectorFromString(@"dealloc")方式来处理,强行得到dealloc这个方法
3.第24行,这里需要在调用一下原来的dealloc方法来处理一些本来应该清空的东西,所以还是得调用一下dealloc方法,但是这里直接调用[self dealloc]就会造成死循环,因为此时已经交换了,你这样直接一调dealloc,不还是调进来交换后的这个方法了吗?哈哈哈,所以要调你交换的这个方法,也就是24行的这种写法,这里有点绕,但是也很容易理解!!!

再次利用运行时轻松解决问题!!!

目前对于运行时的学习只有这两种情况,后续继续增加和补充!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值