面试题答案
一键面试自动释放池差异
- iOS:
- iOS应用通常有一个主线程自动释放池,它在每次事件循环结束时排空。例如,当处理一个触摸事件,在事件处理完成后,主线程自动释放池会释放其中所有自动释放的对象。
- 在iOS中,如果你需要手动创建自动释放池,比如在一个循环中创建大量临时对象时,可以使用
@autoreleasepool
块。例如:
for (int i = 0; i < 10000; i++) {
@autoreleasepool {
NSString *tempString = [NSString stringWithFormat:@"%d", i];
// 这里使用tempString
}
}
这样可以避免在循环中创建的大量临时对象一直占用内存,直到主线程自动释放池排空,从而优化内存使用。 2. macOS:
- macOS的自动释放池机制在应用程序的运行循环中略有不同。它的自动释放池在每次运行循环迭代结束时释放对象。而且,在macOS中,如果你在主线程以外的线程中工作,需要手动管理自动释放池,因为非主线程默认没有自动释放池。例如,在一个自定义线程中:
NSThread *thread = [[NSThread alloc] initWithBlock:^{
@autoreleasepool {
// 线程中的代码,例如创建对象
NSObject *obj = [[NSObject alloc] init];
// 这里使用obj
}
}];
[thread start];
引用计数差异
- iOS和macOS基本原理相同:
- 两者都基于引用计数的内存管理方式,对象有一个引用计数,当引用计数变为0时,对象被释放。例如:
NSObject *obj = [[NSObject alloc] init]; // obj引用计数为1
NSObject *obj2 = obj; // obj引用计数加1,变为2
[obj release]; // obj引用计数减1,变为1
[obj2 release]; // obj引用计数减1,变为0,obj被释放
- ARC(自动引用计数):
- 在iOS和macOS开发中,ARC已成为主流的内存管理方式。ARC会自动在适当的地方插入
retain
、release
和autorelease
代码。例如:
- 在iOS和macOS开发中,ARC已成为主流的内存管理方式。ARC会自动在适当的地方插入
// ARC环境下
NSObject *obj = [[NSObject alloc] init];
// 不需要手动调用release,ARC会在obj不再被使用时自动释放
- 但在某些情况下,如在Core Foundation对象和Objective - C对象混合使用时,仍然需要手动管理引用计数(在ARC环境下通过
__bridge
等关键字来桥接)。例如,在macOS开发中使用Core Foundation的CFString
和Objective - C的NSString
:
CFStringRef cfString = CFStringCreateWithCString(kCFAllocatorDefault, "Hello", kCFStringEncodingUTF8);
NSString *nsString = (__bridge_transfer NSString *)cfString;
// 这里CFString对象的所有权转移给了nsString,ARC会管理nsString的释放
- 在iOS开发中类似,ARC简化了内存管理,但开发人员仍需理解底层原理,以避免循环引用等问题。例如,在一个视图控制器中有一个强引用的属性指向一个对象,而该对象又强引用视图控制器,就会造成循环引用,需要通过使用
weak
或unowned
(iOS 10.0+)来打破循环。例如:
@interface MyViewController : UIViewController
@property (nonatomic, strong) MyObject *myObject;
@end
@interface MyObject : NSObject
@property (nonatomic, weak) MyViewController *viewController; // 使用weak打破循环引用
@end
优化代码总结
- 内存峰值控制:
- 在iOS和macOS开发中,对于大量临时对象的创建,合理使用自动释放池可以控制内存峰值。如前面iOS循环创建字符串的例子,在循环中手动创建自动释放池,可防止大量临时对象在内存中累积。
- 避免循环引用:
- 无论是iOS还是macOS开发,在使用ARC时,要注意对象之间的引用关系,通过使用
weak
或unowned
关键字来避免循环引用,确保对象能在适当的时候被释放。
- 无论是iOS还是macOS开发,在使用ARC时,要注意对象之间的引用关系,通过使用
- Core Foundation与Objective - C对象交互:
- 在混合使用Core Foundation和Objective - C对象时,特别是在macOS开发中,要正确使用桥接关键字(如
__bridge
、__bridge_transfer
等)来管理对象的所有权和引用计数,以避免内存泄漏。
- 在混合使用Core Foundation和Objective - C对象时,特别是在macOS开发中,要正确使用桥接关键字(如