一道经典的 NSString 内存面试题

439 阅读1分钟

1/3,

@property (nonatomic, strong) NSString* strA; 
@property (nonatomic, strong) NSString* strB;

self.strA = @"strA"; 
self.strB = self.strA; 
self.strA = nil;
NSLog(@"self.strB 的值是%@", self.strB);

// self.strB 的值是strA

2/3,

@property (nonatomic, strong) NSString* strA; 
@property (nonatomic, weak) NSString* strB;

self.strA = @"strA"; 
self.strB = self.strA; 
self.strA = nil;
NSLog(@"self.strB 的值是%@", self.strB);

// self.strB 的值是strA

3/3

@property (nonatomic, strong) NSString* strA; 
@property (nonatomic, weak) NSString* strB;

self.strA = [NSMutableString stringWithString: @"strA"];
self.strB = self.strA; 
self.strA = nil;
NSLog(@"self.strB 的值是%@", self.strB);

// self.strB 的值是(null)



OOM

从系统库 signal.h 文件中我们可以找到SIGKILL这个异常信号的解释,它不可以在当前进程被忽略或者被捕获,

我们之前监听异常信号的常规 Crash 捕获方案肯定也就不适用了。

我们在每次 App 启动的时候判断上一次启动进程终止的原因,那么已知的原因有:

  • App 更新了版本
  • App 发生了崩溃
  • 用户手动退出
  • 操作系统更新了版本
  • App 切换到后台之后进程终止

如果上一次启动进程终止的原因不是上述任何一个已知原因的话,就判定上次启动发生了一次FOOM崩溃。


通过上图中引用路径的分析我们发现,所有的图片最终都被TTImagePickController这个类持有,最终排查到是图片选择器模块一次性把用户相册中的所有图片都加载到内存里,极端情况下会发生这个问题。


SwiftUI

  • View
  • Modifier

View 可以如何改变。

  • Layout