MST

星途 面试题库

面试题:Objective-C 状态模式与多线程及内存管理

在一个多线程环境下的iOS应用中,使用Objective-C的状态模式管理一个资源的状态,该资源状态有“初始化”“加载中”“已加载”“错误”。当状态发生变化时,可能会涉及资源的创建、销毁以及数据的读写操作。请详细说明如何在保证状态模式正确运行的同时,处理好多线程带来的资源竞争问题,并且做好内存管理,避免内存泄漏。给出完整的设计方案以及关键代码注释说明。
49.7万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. 设计状态基类

首先定义一个状态基类,其他具体状态类继承自该基类。

// 状态基类
@interface ResourceState : NSObject

// 处理状态变化时的操作
- (void)handleStateChange:(id)resource;

@end

@implementation ResourceState

- (void)handleStateChange:(id)resource {
    // 基类中可以不实现具体逻辑,留给子类实现
}

@end

2. 定义具体状态类

分别实现“初始化”“加载中”“已加载”“错误”这四种状态。

// 初始化状态
@interface InitializingState : ResourceState

@end

@implementation InitializingState

- (void)handleStateChange:(id)resource {
    // 这里可以进行资源创建相关操作,比如初始化数据结构等
    NSLog(@"Resource is initializing.");
}

@end

// 加载中状态
@interface LoadingState : ResourceState

@end

@implementation LoadingState

- (void)handleStateChange:(id)resource {
    // 处理加载中的逻辑,如显示加载指示器等
    NSLog(@"Resource is loading.");
}

@end

// 已加载状态
@interface LoadedState : ResourceState

@end

@implementation LoadedState

- (void)handleStateChange:(id)resource {
    // 可以在这里进行数据读取操作
    NSLog(@"Resource is loaded.");
}

@end

// 错误状态
@interface ErrorState : ResourceState

@end

@implementation ErrorState

- (void)handleStateChange:(id)resource {
    // 处理错误逻辑,如释放资源等
    NSLog(@"Resource has an error.");
}

@end

3. 定义资源类

资源类持有当前状态,并提供状态切换方法。

@interface Resource : NSObject

@property (nonatomic, strong) ResourceState *currentState;

// 切换状态方法
- (void)changeState:(ResourceState *)newState;

@end

@implementation Resource

- (void)changeState:(ResourceState *)newState {
    // 切换状态前,处理旧状态下可能需要的清理操作
    [self.currentState handleStateChange:self];
    self.currentState = newState;
    // 切换状态后,执行新状态的相关操作
    [self.currentState handleStateChange:self];
}

@end

4. 处理多线程资源竞争和内存管理

为了处理多线程资源竞争问题,使用 NSLock 或者 dispatch_queue。这里以 dispatch_queue 为例。

@interface ResourceManager : NSObject

@property (nonatomic, strong) Resource *resource;
// 串行队列,用于处理资源相关操作,避免资源竞争
@property (nonatomic, strong) dispatch_queue_t resourceQueue;

+ (instancetype)sharedManager;

@end

@implementation ResourceManager

+ (instancetype)sharedManager {
    static ResourceManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[ResourceManager alloc] init];
        manager.resource = [[Resource alloc] init];
        manager.resource.currentState = [[InitializingState alloc] init];
        // 创建一个串行队列
        manager.resourceQueue = dispatch_queue_create("com.example.resourceQueue", DISPATCH_QUEUE_SERIAL);
    });
    return manager;
}

// 在队列中安全地切换资源状态
- (void)safeChangeState:(ResourceState *)newState {
    dispatch_async(self.resourceQueue, ^{
        [self.resource changeState:newState];
    });
}

@end

5. 内存管理

通过合理的对象生命周期管理来避免内存泄漏。在状态类和资源类的 dealloc 方法中释放相关资源。

// 例如在Resource类的dealloc方法中
@implementation Resource

- (void)dealloc {
    // 释放可能持有的资源
    self.currentState = nil;
}

@end

// 各个状态类也类似,释放各自持有的资源
@implementation InitializingState

- (void)dealloc {
    // 释放初始化状态下持有的资源
}

@end

这样,通过上述设计方案,在保证状态模式正确运行的同时,利用 dispatch_queue 处理了多线程带来的资源竞争问题,并通过合理的对象生命周期管理做好了内存管理,避免了内存泄漏。