- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr = [NSArray arrayWithObject:@"sun"];
}
前言
前天挖了一个坑,今天先把它填上。
本文适合简单快速的回答面试官的问题。对于更深的相关知识,请关注后续的文章或者自行查阅相关资料。
简单版答案
在 ARC 下,+arrayWithObject:
方法会自动调用 -autorelease
方法。
调用后,该变量会被添加到自动释放池。
在主线程中,临时变量会在 runloop
运行结束时释放。
在非主线程中,临时变量会在 线程退出时释放。
所以,当有大量的临时对象时,官方建议我们使用 @autoreleasepool
进行内存管理。
NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
@autoreleasepool {
NSError *error;
NSString *fileContents = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
}
}
测试
为了测试,本文创建了一个类,SunObject
并实现了 -dealloc
方法。
测试代码
@interface SunObject : NSObject
@end
@implementation SunObject
- (void)dealloc {
}
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
__unused NSMutableArray *arr = [NSMutableArray arrayWithObject:[SunObject new]];
}
Allocations
通过 Allocations 工具,我们可以查看变量的生命周期。如下图所示。
下面是手动打印的调用栈。可以明显发现 释放操作是在 libobjc.A.dylib
(anonymous namespace)::AutoreleasePoolPage::pop(void*)`的后面。
(lldb) bt
* thread #1: tid = 0x44ecce, 0x0000000105118597 内存管理`-[SunObject dealloc](self=0x00007fbbb0e09650, _cmd="dealloc") + 23 at ViewController.m:22, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000105118597 内存管理`-[SunObject dealloc](self=0x00007fbbb0e09650, _cmd="dealloc") + 23 at ViewController.m:22
frame #1: 0x000000010562eafe libobjc.A.dylib`objc_object::sidetable_release(bool) + 232
frame #2: 0x0000000105a8498d CoreFoundation`-[__NSArrayM dealloc] + 157
frame #3: 0x000000010562eafe libobjc.A.dylib`objc_object::sidetable_release(bool) + 232
frame #4: 0x000000010562f0b8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 488
frame #5: 0x00000001089c58d0 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 32
frame #6: 0x00000001089c5741 FrontBoardServices`-[FBSSerialQueue _performNext] + 178
frame #7: 0x00000001089c5aca FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
frame #8: 0x0000000105acc301 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #9: 0x0000000105ac222c CoreFoundation`__CFRunLoopDoSources0 + 556
frame #10: 0x0000000105ac16e3 CoreFoundation`__CFRunLoopRun + 867
frame #11: 0x0000000105ac10f8 CoreFoundation`CFRunLoopRunSpecific + 488
frame #12: 0x0000000105f57f21 UIKit`-[UIApplication _run] + 402
frame #13: 0x0000000105f5cf09 UIKit`UIApplicationMain + 171
frame #14: 0x0000000105118b9f 内存管理`main(argc=1, argv=0x00007fff5aae76a0) + 111 at main.m:14
frame #15: 0x000000010838092d libdyld.dylib`start + 1
(lldb)