MST
星途 面试题库

面试题:Objective-C 内存警告下的单例资源释放技巧

在一个使用 Objective-C 开发的项目中,存在多个单例类用于管理不同的系统资源,当收到内存警告时,如何设计一种机制,既能保证单例在正常情况下的唯一性,又能在内存紧张时安全且有效地释放其所占用的资源,说明设计思路并给出核心代码示例。
36.4万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 单例创建:使用标准的 Objective-C 单例模式创建单例对象,确保在正常情况下单例的唯一性。
  2. 内存警告处理:监听系统的内存警告通知 UIApplicationDidReceiveMemoryWarningNotification。在收到通知时,检查单例对象所占用资源情况,如果资源占用过多且当前不是必须使用的,释放这些资源。同时,为了能在之后重新获取资源,需要记录释放前的状态等必要信息。
  3. 资源重新获取:当再次需要使用单例对象的资源时,检查资源是否已释放,如果已释放则根据之前记录的信息重新获取或初始化资源。

核心代码示例

#import <Foundation/Foundation.h>

@interface MySingleton : NSObject

@property (nonatomic, strong) id someResource; // 单例管理的资源

+ (instancetype)sharedInstance;
- (void)releaseResource;
- (void)reacquireResource;

@end

@implementation MySingleton

static MySingleton *sharedInstance = nil;

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        // 初始化资源
        sharedInstance.someResource = [[NSObject alloc] init]; 
    });
    return sharedInstance;
}

- (void)releaseResource {
    self.someResource = nil;
}

- (void)reacquireResource {
    if (!self.someResource) {
        self.someResource = [[NSObject alloc] init];
    }
}

@end

// 在 AppDelegate 中监听内存警告通知
#import "AppDelegate.h"
#import "MySingleton.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 注册内存警告通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    return YES;
}

- (void)handleMemoryWarning {
    MySingleton *singleton = [MySingleton sharedInstance];
    // 判断资源占用情况,这里简单示例,实际需根据具体业务判断
    if (/* 资源占用过多且当前非必须 */ YES) {
        [singleton releaseResource];
    }
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

当单例对象的资源在内存警告时被释放,在后续使用相关资源时,可调用 reacquireResource 方法重新获取资源。如:

MySingleton *singleton = [MySingleton sharedInstance];
[singleton reacquireResource];
// 使用 singleton.someResource