MST

星途 面试题库

面试题:Objective-C运行时机制在实际开发中的深度应用

详细说明Objective-C运行时机制(runtime)的核心概念,如类对象、元类、方法列表等。并举例阐述runtime在诸如消息转发、动态方法解析、关联对象等高级特性中的应用原理及实际开发场景。
47.9万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

Objective-C运行时机制核心概念

  1. 类对象(Class Object)
    • 每个类在运行时都有一个对应的类对象。类对象存储了该类的相关信息,比如类名、超类(superclass)指针、实例变量的布局信息、方法列表等。例如,对于一个Person类,运行时会创建一个代表Person类的类对象。通过[Person class]可以获取到这个类对象。
    • 类对象是类的实例的模板,实例通过类对象来分配内存、调用方法等。
  2. 元类(Meta - Class)
    • 元类也是一种类对象,它存储了类方法(以+开头的方法)的列表。每个类都有一个与之关联的元类。元类的超类是其类的超类的元类(根元类的超类是NSObject的元类,NSObject元类的超类是NSObject本身)。
    • 类方法实际上是存储在元类的方法列表中。当调用一个类方法时,比如[Person someClassMethod],消息是发送给Person类的元类。
  3. 方法列表(Method List)
    • 类对象和元类都有方法列表。类对象的方法列表存储实例方法(以-开头的方法),元类的方法列表存储类方法。方法列表中的每个方法由一个SEL(选择器)和一个IMP(实现)组成。SEL是方法的唯一标识符,IMP是方法实际的实现代码的指针。例如,对于Person类的- (void)sayHello方法,在类对象的方法列表中,会有一个对应的SEL@selector(sayHello),以及指向sayHello方法实现代码的IMP

runtime在高级特性中的应用原理及实际开发场景

  1. 消息转发(Message Forwarding)
    • 应用原理:当向一个对象发送一条它无法识别的消息时,runtime会启动消息转发机制。首先是动态方法解析,runtime会询问类是否可以动态添加一个处理该消息的方法(+ (BOOL)resolveInstanceMethod:(SEL)sel用于实例方法,+ (BOOL)resolveClassMethod:(SEL)sel用于类方法)。如果动态方法解析没有处理该消息,接着进入备用接收者阶段,runtime会询问对象是否能把消息转发给其他对象处理(- (id)forwardingTargetForSelector:(SEL)aSelector)。如果备用接收者也没有处理,最后进入完整的消息转发阶段,runtime会创建一个NSInvocation对象,包含消息的所有信息,开发者可以在- (void)forwardInvocation:(NSInvocation *)anInvocation方法中手动处理该消息,或者调用父类的forwardInvocation:方法继续转发。
    • 实际开发场景:在开发框架时,可能会遇到一些动态的需求,比如调用一些可能在运行时才会添加的方法。例如,在一些插件化开发中,插件可能会在运行时注册一些方法,主程序在不知道这些方法提前存在的情况下,通过消息转发机制可以动态调用这些方法。
  2. 动态方法解析(Dynamic Method Resolution)
    • 应用原理:在消息转发的第一步,runtime会调用类的+ (BOOL)resolveInstanceMethod:(SEL)sel(实例方法)或+ (BOOL)resolveClassMethod:(SEL)sel(类方法)。如果开发者在这些方法中通过class_addMethod函数动态添加了对应的方法实现,runtime就会重新尝试发送消息,此时新添加的方法就会被调用。
    • 实际开发场景:在一些动态功能扩展的场景中很有用。比如,在一个游戏开发中,游戏可能会根据玩家的操作在运行时动态添加一些特殊的技能方法,通过动态方法解析可以在运行时添加这些技能方法的实现并调用。
  3. 关联对象(Associated Objects)
    • 应用原理:runtime提供了objc_setAssociatedObjectobjc_getAssociatedObjectobjc_removeAssociatedObjects等函数来实现关联对象。通过这些函数,可以在运行时为一个对象动态添加额外的属性,而不需要在类的定义中声明。这些关联对象是基于runtime的散列表实现的,每个对象都有一个关联对象的列表。
    • 实际开发场景:在category(类别)中添加属性时非常有用。因为category不能直接添加实例变量,通过关联对象可以实现类似添加属性的效果。例如,在开发一个图片处理的category时,可以通过关联对象为UIImage对象添加一些自定义的属性,如图片的来源描述等,而不需要修改UIImage类的原有代码。