iOS面试题(十七)Runtime --  动态添加方法&动态方法解析

 

4.动态运行时(RunTime)

  • 基础数据结构
  • 对象、类对象、元类对象是怎么理解的?以及他们之间的关系是怎样的(实例与类对象之间的关系以及类对象与元类对象之间的关系)?
  • OC语言中的消息传递机制是怎样的?
  • 缓存查找  (我们进行方法查找的过程当中,如何进行缓存的方法查找?会使用到系统或者说Runtime中一个方法缓存的机制,这个机制又是怎样运行的呢?)
  • 消息转发流程是怎样的?
  • Method-Swizzling(方法混写)是Runtime的一种运用(我们可以再运行时,去替换一些方法的实现,也得益于动态运行时这一个特性),可能会结合实际的场景,比如说通过时长统计框架这样的考察来了解对于Runtime的Methood-Swizzling技术的一个实际的运用
  • 动态添加方法(Runtime提供的功能实现)
  • 动态方法解析(Runtime提供的功能实现)

动态添加方法

你是否有使用过performSelector这个系统方法(performSelector应用场景)?
 


void testImp (void)
{
    NSLog(@"test invoke");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    // 如果是test方法 打印日志
    
    if (sel == @selector(test)) {
        NSLog(@"resolveInstanceMethod:");

       // 动态添加test方法的实现
       /*参数:为哪个类添加方法,
              添加方法对应的选择器名称,
              方法的具体实现,
              方法所对应的返回值类型以及参数的个数和每个参数的类型
               v 函数的返回值为void   @当前对象    : sel这个类型
        */
        class_addMethod(self, @selector(test), testImp, "v@:");
        
        return YES;
    }
    else{
        // 返回父类的默认调用
        return [super resolveInstanceMethod:sel];
    }
}

1.一个类在编译时没有某个方法,在运行时才产生了这个方法,
就需要调用performSelector来调用这个方法,面试官借用这个来考察Runtime动态添加方法的特性.
上面的例子,我们调用了test,却没有实现它,所以需要在运行时去添加它的实现
在resolveInstanceMethod为test方法(选择器)添加具体实现

Runtime-动态方法解析

你是否使用过@dynamic这样一个编译器关键字?
1.当我们把声明的属性在实现中将它标识为@dynamic,就相当于get方法和set方法是在运行时添加,而不是在编译时声明好还有具体的实现,实际也是考察Runtime的相关内容

2.编译时语言和动态运行时语言的区别

  • 动态运行时语言将函数决议推迟到运行时,实际上就是在运行时再去为方法添加具体的执行函数
    当我们把属性标识为@dynamic时,代表着不需要编译器在编译时为我们生成这个属性的get方法和set方法的具体实现,
    而是在运行时当我们具体的调用了get和set方法时,再去为它添加具体实现,只有动态运行时语言支持这种功能
  • 编译时语言是在编译期进行函数决议,在编译期就决定了具体实现,在运行时无法修改

RunTime实战:

1、[obj foo]和objc_msgSend()函数的关系([obj foo](消息传递或者说发送消息,向obj对象发送foo这条消息),它和objc_msgSend()这个函数有什么关系)

  • [obj foo]在经过编译器处理之后,就变成了objc_msgSend()函数,这个参数第一个是obj,第二个参数是foo选择器
  • 由于[obj foo]这个方法没有其他参数,所以objc_msgSend()这个函数参数只有两个
    在编译之后呢,就把[obj foo]转化成objc_msgSend()这个函数调用了,
    接下来就开始了Runtime的消息传递过程

2.runtime如何通过Selector找到对应的IMP地址?

  • 其实就是消息传递机制本质,先查找当前实例对应类对象的缓存,
    是否有Selector对应的缓存IMP实现,若有,则返回给调用方。
    若没有,再根据当前类的方法列表,去查找Selector找到对应的IMP,
    当前类如果没有,再根据当前类的superClass指针逐级查找父类方法列表,然后查找Selector所对应的IMP实现

3.能否向编译后的类中增加实例变量?

  • runtime支持在运行时动态添加类,要注意是编译后的类还是动态添加的类
  • 编译前创建的类,已经完成了实例变量的布局,在具体分析RunTime的数据结构当中知道class_ro_t,因为是readonly,所以在编译后是无法修改的,所以编译后的类,不能为他增加实例变量

4.能否向动态添加的类中增加实例变量?

  • 但是可以向动态添加的类中添加实例变量,
  • 因为在动态添加类的过程中,只要调用它的注册类对方法之前,完成实例变量的添加,就可以实现。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NSStringiOS开发中非常常用的字符串,其中substringFromIndex、substringWithRange和substringToIndex是NSString中的三个常用方法,用于截取字符串的一部分。下面分别介绍它们的使用方法。 1. substringFromIndex方法方法用于截取字符串从指定位置到字符串结尾的所有字符,返回截取后的字符串。它的方法签名如下: ``` - (NSString *)substringFromIndex:(NSUInteger)from; ``` 其中,from是一个NSUInteger型的参数,表示要截取的起始位置,从0开始计数。 示例代码: ``` NSString *str = @"Hello World"; NSString *subStr = [str substringFromIndex:6]; NSLog(@"%@", subStr); // 输出:"World" ``` 2. substringWithRange方法方法用于截取字符串从指定范围内的所有字符,返回截取后的字符串。它的方法签名如下: ``` - (NSString *)substringWithRange:(NSRange)range; ``` 其中,range是一个NSRange型的结构体,用来指定要截取的字符串的范围。 示例代码: ``` NSString *str = @"Hello World"; NSRange range = NSMakeRange(6, 5); NSString *subStr = [str substringWithRange:range]; NSLog(@"%@", subStr); // 输出:"World" ``` 3. substringToIndex方法方法用于截取字符串从字符串开头到指定位置的所有字符,返回截取后的字符串。它的方法签名如下: ``` - (NSString *)substringToIndex:(NSUInteger)to; ``` 其中,to是一个NSUInteger型的参数,表示要截取的结束位置,从0开始计数。 示例代码: ``` NSString *str = @"Hello World"; NSString *subStr = [str substringToIndex:5]; NSLog(@"%@", subStr); // 输出:"Hello" ``` 以上就是NSString中substringFromIndex、substringWithRange和substringToIndex方法的使用方法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值