MST
星途 面试题库

面试题:Objective-C 协议与内存管理及动态特性

在Objective-C中,当使用协议进行对象交互时,如何确保内存管理的正确性,尤其是在存在循环引用的情况下?另外,在运行时,如何动态地为一个对象添加对新协议的遵循,并在运行时检查对象是否支持协议中的某个可选方法,详细说明实现思路及涉及到的相关runtime机制。
36.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

确保内存管理正确性及避免循环引用

  1. 避免循环引用
    • 弱引用:在属性声明时,对于可能产生循环引用的对象,使用weak修饰符。例如,在两个对象通过协议进行交互时,如果A对象持有B对象,B对象又通过协议回调持有A对象,B对象中持有A对象的属性应声明为weak
    @interface B : NSObject
    @property (nonatomic, weak) id <ProtocolA> aObject;
    @end
    
    • 无主引用:使用unowned修饰符(在ARC下,unowned类似weak,但unowned不会自动置为nil,使用时要确保对象存在,否则可能导致野指针)。例如:
    @interface B : NSObject
    @property (nonatomic, unowned) id <ProtocolA> aObject;
    @end
    
  2. 内存管理规范
    • 遵循引用计数原则:在手动内存管理(MRC)下,要确保正确的retainreleaseautorelease调用。在ARC下,编译器会自动处理引用计数,但仍需注意对象的生命周期,避免提前释放或过度保留。
    • 对象生命周期控制:确保在合适的时机释放对象,比如在对象的dealloc方法中清理相关资源,在ARC下,dealloc方法中主要处理非内存相关资源的释放,如关闭文件描述符等。

运行时动态添加对新协议的遵循

  1. 实现思路
    • 使用Objective - C的运行时(runtime)机制。在运行时,可以通过class_addProtocol函数为类动态添加协议。首先需要获取类的元数据,然后调用class_addProtocol函数将新协议添加到类中。
    • 同时,需要实现协议中的方法。可以通过class_addMethod函数动态为类添加方法实现。
  2. 示例代码
    #import <objc/runtime.h>
    // 定义新协议
    @protocol NewProtocol <NSObject>
    - (void)newProtocolMethod;
    @end
    
    @interface MyClass : NSObject
    @end
    
    @implementation MyClass
    // 动态添加协议方法的实现
    void newProtocolMethodIMP(id self, SEL _cmd) {
        NSLog(@"执行新协议方法");
    }
    
    + (void)load {
        Class myClass = [self class];
        // 添加协议
        class_addProtocol(myClass, @protocol(NewProtocol));
        // 添加协议方法实现
        class_addMethod(myClass, @selector(newProtocolMethod), (IMP)newProtocolMethodIMP, "v@:");
    }
    @end
    

运行时检查对象是否支持协议中的某个可选方法

  1. 实现思路
    • 利用运行时的class_getInstanceMethod函数。首先获取对象的类,然后通过class_getInstanceMethod函数检查类是否实现了协议中的可选方法。
    • 也可以使用respondsToSelector:方法,该方法在运行时会检查对象是否能响应某个选择器(方法),可以用于检查对象是否支持协议中的可选方法。
  2. 示例代码
    MyClass *obj = [[MyClass alloc] init];
    // 使用class_getInstanceMethod检查
    Method method = class_getInstanceMethod([obj class], @selector(newProtocolMethod));
    if (method) {
        NSLog(@"对象支持新协议方法");
    }
    // 使用respondsToSelector:检查
    if ([obj respondsToSelector:@selector(newProtocolMethod)]) {
        NSLog(@"对象支持新协议方法");
    }
    

在运行时检查对象是否支持协议中的可选方法,class_getInstanceMethod更底层,直接从类的方法列表中查找;respondsToSelector:相对更便捷,是NSObject的实例方法,会按照继承体系等规则查找方法实现。