MST

星途 面试题库

面试题:Objective-C动态创建类与对象在复杂场景下的应用与优化

假设你正在开发一个大型的Objective-C应用,需要根据运行时获取的不同配置动态创建多种类型的类,这些类之间存在复杂的继承和组合关系,且对性能要求极高。请详细阐述你会如何设计动态创建类与对象的架构,包括如何优化内存使用、避免潜在的内存泄漏和提高类与对象创建及方法调用的效率。同时说明在这种场景下,如何处理动态类的生命周期管理以及与其他静态类的交互。
11.1万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

动态创建类与对象的架构设计

  1. 使用运行时函数:在Objective - C中,objc_allocateClassPairclass_addIvarclass_addMethod等运行时函数可用于动态创建类。例如,根据配置信息确定类的属性和方法,然后使用这些函数创建相应的类。
Class newClass = objc_allocateClassPair(superclass, "DynamicClassName", 0);
class_addIvar(newClass, "ivarName", sizeof(int), log2(sizeof(int)), @encode(int));
class_addMethod(newClass, @selector(methodName), (IMP)methodImplementation, methodTypeEncoding);
objc_registerClassPair(newClass);
  1. 基于工厂模式:创建一个类工厂,根据运行时配置决定创建哪种类型的类。这样可以将创建逻辑集中管理,方便维护和扩展。
@interface ClassFactory : NSObject
+ (id)createObjectWithConfiguration:(NSDictionary *)configuration;
@end

@implementation ClassFactory
+ (id)createObjectWithConfiguration:(NSDictionary *)configuration {
    NSString *className = configuration[@"className"];
    Class targetClass = NSClassFromString(className);
    if (!targetClass) {
        // 动态创建类的逻辑
        targetClass = createDynamicClass(configuration);
    }
    return [[targetClass alloc] init];
}
@end

优化内存使用

  1. 对象池:对于频繁创建和销毁的动态对象,可以使用对象池技术。预先创建一定数量的对象并放入池中,需要时从池中获取,使用完毕后放回池中,避免频繁的内存分配和释放。
@interface ObjectPool : NSObject
+ (instancetype)sharedPool;
- (id)getObject;
- (void)returnObject:(id)object;
@end

@implementation ObjectPool {
    NSMutableArray *_pool;
}
+ (instancetype)sharedPool {
    static ObjectPool *pool = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        pool = [[ObjectPool alloc] init];
    });
    return pool;
}
- (instancetype)init {
    self = [super init];
    if (self) {
        _pool = [NSMutableArray array];
        // 预先创建对象放入池中
        for (int i = 0; i < 10; i++) {
            id obj = [[DynamicClass alloc] init];
            [_pool addObject:obj];
        }
    }
    return self;
}
- (id)getObject {
    if (_pool.count > 0) {
        return [_pool lastObject];
    }
    // 如果池为空,创建新对象
    return [[DynamicClass alloc] init];
}
- (void)returnObject:(id)object {
    [_pool addObject:object];
}
@end
  1. 弱引用:当动态类对象与其他对象存在关联时,尽量使用弱引用,避免循环引用导致的内存泄漏。例如,在视图控制器与动态创建的视图之间的关联。
@interface ViewController : UIViewController
@property (nonatomic, weak) DynamicView *dynamicView;
@end

避免内存泄漏

  1. ARC(自动引用计数):利用ARC机制,让编译器自动管理内存,减少手动内存管理错误。但对于动态创建的类,仍需注意对象之间的引用关系。
  2. 内存分析工具:使用 Instruments 中的Leaks工具,在开发和测试阶段检测内存泄漏问题。通过分析内存使用情况,找出潜在的泄漏点并进行修复。

提高类与对象创建及方法调用的效率

  1. 缓存类信息:在创建动态类时,缓存类的元数据信息,如属性列表、方法列表等,避免每次都从运行时获取。
@interface DynamicClassCache : NSObject
@property (nonatomic, strong) NSMutableDictionary<NSString *, Class> *classCache;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSDictionary<NSString *, Ivar>> *ivarCache;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSDictionary<SEL, Method>> *methodCache;
+ (instancetype)sharedCache;
@end

@implementation DynamicClassCache
+ (instancetype)sharedCache {
    static DynamicClassCache *cache = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cache = [[DynamicClassCache alloc] init];
        cache.classCache = [NSMutableDictionary dictionary];
        cache.ivarCache = [NSMutableDictionary dictionary];
        cache.methodCache = [NSMutableDictionary dictionary];
    });
    return cache;
}
@end
  1. 优化方法调度:对于频繁调用的方法,可以使用IMP缓存。在第一次调用方法时,获取方法的IMP并缓存起来,后续调用直接通过缓存的IMP进行,减少动态方法解析的开销。
@interface DynamicObject : NSObject
@property (nonatomic, strong) NSMutableDictionary<SEL, IMP> *methodIMPCache;
@end

@implementation DynamicObject
- (IMP)cachedIMPForSelector:(SEL)sel {
    IMP imp = self.methodIMPCache[sel];
    if (!imp) {
        imp = [self methodForSelector:sel];
        self.methodIMPCache[sel] = imp;
    }
    return imp;
}
@end

动态类的生命周期管理

  1. 对象创建与销毁:确保动态创建的对象在不再使用时能够正确释放。可以在对象内部实现dealloc方法,进行必要的资源清理,如关闭文件、释放网络连接等。
@interface DynamicObject : NSObject
@property (nonatomic, strong) NSFileHandle *fileHandle;
@end

@implementation DynamicObject
- (void)dealloc {
    [self.fileHandle closeFile];
    self.fileHandle = nil;
}
@end
  1. 对象引用计数:在手动管理内存(非ARC环境)时,要正确维护对象的引用计数。当对象的引用计数为0时,及时释放内存。在ARC环境下,依赖编译器自动管理引用计数,但仍需注意对象之间的引用关系,避免循环引用。

与其他静态类的交互

  1. 协议与代理:通过定义协议,让动态类和静态类遵循相同的协议,实现松耦合的交互。静态类可以作为动态类的代理,处理动态类的事件和回调。
@protocol DynamicClassDelegate <NSObject>
- (void)dynamicClassDidFinishTask:(DynamicClass *)dynamicClass;
@end

@interface StaticClass : NSObject <DynamicClassDelegate>
@end

@implementation StaticClass
- (void)dynamicClassDidFinishTask:(DynamicClass *)dynamicClass {
    // 处理动态类完成任务的逻辑
}
@end

@interface DynamicClass : NSObject
@property (nonatomic, weak) id<DynamicClassDelegate> delegate;
@end

@implementation DynamicClass
- (void)finishTask {
    if ([self.delegate respondsToSelector:@selector(dynamicClassDidFinishTask:)]) {
        [self.delegate dynamicClassDidFinishTask:self];
    }
}
@end
  1. 通知中心:使用NSNotificationCenter,动态类和静态类可以通过发送和接收通知进行交互。动态类在特定事件发生时发送通知,静态类注册接收该通知并处理相应逻辑。
// 动态类发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"DynamicClassEvent" object:self userInfo:nil];

// 静态类接收通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDynamicClassEvent:) name:@"DynamicClassEvent" object:nil];
- (void)handleDynamicClassEvent:(NSNotification *)notification {
    // 处理通知逻辑
}