MST

星途 面试题库

面试题:Objective-C Runtime下关联对象的原理与应用场景

解释在Objective-C运行时中,关联对象是如何实现的?阐述其底层数据结构和相关函数的作用。并举例说明至少两个在实际开发中关联对象的应用场景。
50.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

关联对象的实现

在Objective-C运行时,关联对象是通过objc_setAssociatedObjectobjc_getAssociatedObject等函数来实现的。运行时系统在对象的结构体中维护了一个额外的AssociationsManagerAssociationsHashMap来管理关联对象。当给一个对象设置关联对象时,会将对象的指针作为key,关联对象的信息(包括关联策略等)作为value存储在AssociationsHashMap中。

底层数据结构

  1. AssociationsManager:这是一个管理类,它维护了一个线程安全的AssociationsHashMap
  2. AssociationsHashMap:是一个哈希表,以对象指针作为key,以ObjectAssociationMap作为value。
  3. ObjectAssociationMap:也是一个哈希表,以关联对象的key(通常是一个NSString对象)作为key,以ObjcAssociation作为value。
  4. ObjcAssociation:这个结构体存储了关联对象和关联策略。

相关函数的作用

  1. objc_setAssociatedObject:用于设置关联对象,它接收三个参数:目标对象、关联的key、关联的对象以及关联策略。例如:
NSString *key = @"myKey";
NSString *value = @"myValue";
objc_setAssociatedObject(self, (__bridge const void *)(key), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  1. objc_getAssociatedObject:用于获取关联对象,接收目标对象和关联的key作为参数。例如:
NSString *key = @"myKey";
NSString *value = objc_getAssociatedObject(self, (__bridge const void *)(key));
  1. objc_removeAssociatedObjects:用于移除对象所有的关联对象。

实际开发中的应用场景

  1. 给分类添加属性:在Objective-C中,分类不能直接添加实例变量,但可以通过关联对象来实现类似的效果。比如,给UIButton分类添加一个自定义的属性:
@interface UIButton (CustomProperty)
@property (nonatomic, strong) NSString *customTitle;
@end

@implementation UIButton (CustomProperty)
- (void)setCustomTitle:(NSString *)customTitle {
    objc_setAssociatedObject(self, @selector(customTitle), customTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSString *)customTitle {
    return objc_getAssociatedObject(self, @selector(customTitle));
}
@end
  1. 为视图添加额外数据:在处理视图时,有时候需要给视图添加一些额外的数据,而不需要在视图类中定义属性。例如,在一个复杂的视图层级中,为某个UIView添加一个唯一标识:
UIView *myView = [[UIView alloc] init];
NSString *uniqueID = @"12345";
objc_setAssociatedObject(myView, @"uniqueID", uniqueID, OBJC_ASSOCIATION_COPY_NONATOMIC);

在后续处理中可以通过objc_getAssociatedObject获取这个唯一标识进行相关操作。