Ruu*_*uug 2 memory-management objective-c
一个简单的程序:
-(void)doSomething {
NSLog(@"self rc=%d", [self retainCount]);
[self performSelector:@selector(doMe:) withObject:nil afterDelay:0 inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
NSLog(@"self rc=%d", [self retainCount]);
}
-(void)doMe:(id)object {
NSLog(@"i'm done");
NSLog(@"self rc=%d", [self retainCount]);
}
Run Code Online (Sandbox Code Playgroud)
输出:
self rc=1
self rc=2
i'm done
self rc=2
Run Code Online (Sandbox Code Playgroud)
为什么保留计数增加到并保持在2?
nac*_*o4d 13
从- [NSObject performSelector:withObject:afterDelay:inModes:]文档:
2013/11/01答案
正如预期的那样,文档似乎更新了,现在他们并没有说目标对象被保留,但他们仍然提到了runloop中的预定计时器.
如果使用NSTimer,则该对象必须由某人保留,否则将无法保证可以执行选择器,因为没有人可以确保该对象仍然存活.如果不使用ARC,weak它会崩溃.在我看来,Apple编辑其文档时没有提到实现细节,尽管我认为这很明显.
上面的文档并没有提到" 保留 "一词,但并不意味着目标不会被保留.
这是我在模拟器iOS7.0中的调试器中尝试过的:
(lldb) p (int)[self retainCount]
(int) $1 = 8
(lldb) expr (void)[self performSelector:@selector(description) withObject:nil afterDelay:1.0]
(lldb) p (int)[self retainCount]
(int) $2 = 9
(lldb) expr (void)[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(description) object:nil]
(lldb) p (int)[self retainCount]
(int) $3 = 8
Run Code Online (Sandbox Code Playgroud)
结论:保留了对象,但这不是我们应该关心的.先生解决了:p
上一个答案:(仍然有效)
此方法保留接收器和anArgument参数,直到执行选择器.
因为如果没有保留该对象,则该对象可能会在执行之前被释放,并且您的应用程序将崩溃.
设置并尝试使用NSTimers触发方法时的逻辑是相同的.如果目标对象不再存在(已释放),实际触发计时器,您的应用程序将崩溃.因此performSelector:withObject:afterDelay:...,它的朋友们可以让我们的生活变得更轻松,因为它可以确保应用程序在计时器被触发时不会崩溃;)
希望能帮助到你