检查 NSTimer 是否有效时崩溃?
Crash when checking if NSTimer isValid?
我在控制台中收到此异常:
Error:
2015-06-25 23:12:01.841 Copyfeed for Mac[9512:584232]
-[_NSViewLayoutAux invalidate]: unrecognized selector sent to instance 0x6000001657c0
检查我的计时器是否 valid/and 使它们无效时。
if ([_staticTimer isValid]) {
[_staticTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
if ([_selectionTimer isValid]) {
[_selectionTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
这是我的新代码:
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
@property (strong )NSTimer *staticTimer;
@property (strong )NSTimer *selectionTimer;
现在当我调试僵尸对象时出现这个错误。
2015-06-26 00:39:45.523 Copyfeed for Mac[11191:824502] ***
-[CFRunLoopTimer release]: message sent to deallocated instance 0x608000175e40
使其无效后,应将 NSTimer
对象设置为 nil
。
invalidate
方法也执行 release
。
如果您不这样做,在其上调用方法 isValid
可能会导致崩溃。
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
// do something
}
点击这里
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
//_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
_staticTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
来自文档:
Because the run loop maintains the timer, from the perspective of
memory management there's typically no need to keep a reference to a
timer after you’ve scheduled it. Since the timer is passed as an
argument when you specify its method as a selector, you can invalidate
a repeating timer when appropriate within that method. In many
situations, however, you also want the option of invalidating the
timer—perhaps even before it starts. In this case, you do need to keep
a reference to the timer, so that you can send it an invalidate
message whenever appropriate. If you create an unscheduled timer (see
“Unscheduled Timers”), then you must maintain a strong reference to
the timer (in a reference-counted environment, you retain it) so that
it is not deallocated before you use it.
所以你应该让计时器变弱而不是变强
这里有几个潜在的问题。
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
您在这里所做的是覆盖 selectionTimer
,即使它可能仍包含一个仍在 运行 循环中安排的计时器。所以如果你在这里重置属性,你也应该确保在这样做之前调用[_selectionTimer invalidate]
。
根据计时器启动时您在做什么,这可以解释 CFRunLoopTimer
上的崩溃。
在使用 NSTimer
时证明对我非常有帮助的一般性建议:我建议将所有包含预定计时器的属性声明为 weak
,因为它们由运行 循环。这样,您不需要在使它们无效后将它们显式设置为 nil
,而是每次您想要摆脱它时只需调用 invalidate
,它也会自动变为 [=16] =] 一旦它被 运行 循环触发,释放它可能持有的所有数据。
请注意,这仍然需要您调用 invalidate
以防您想要取消计时器或在更换计时器之前调用,但在这样做之后您不再需要将其设置为 nil
。
我在控制台中收到此异常:
Error:
2015-06-25 23:12:01.841 Copyfeed for Mac[9512:584232] -[_NSViewLayoutAux invalidate]: unrecognized selector sent to instance 0x6000001657c0
检查我的计时器是否 valid/and 使它们无效时。
if ([_staticTimer isValid]) {
[_staticTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
if ([_selectionTimer isValid]) {
[_selectionTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
这是我的新代码:
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
@property (strong )NSTimer *staticTimer;
@property (strong )NSTimer *selectionTimer;
现在当我调试僵尸对象时出现这个错误。
2015-06-26 00:39:45.523 Copyfeed for Mac[11191:824502] *** -[CFRunLoopTimer release]: message sent to deallocated instance 0x608000175e40
使其无效后,应将 NSTimer
对象设置为 nil
。
invalidate
方法也执行 release
。
如果您不这样做,在其上调用方法 isValid
可能会导致崩溃。
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
// do something
}
点击这里
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
//_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
_staticTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
来自文档:
Because the run loop maintains the timer, from the perspective of memory management there's typically no need to keep a reference to a timer after you’ve scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it.
所以你应该让计时器变弱而不是变强
这里有几个潜在的问题。
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}
您在这里所做的是覆盖 selectionTimer
,即使它可能仍包含一个仍在 运行 循环中安排的计时器。所以如果你在这里重置属性,你也应该确保在这样做之前调用[_selectionTimer invalidate]
。
根据计时器启动时您在做什么,这可以解释 CFRunLoopTimer
上的崩溃。
在使用 NSTimer
时证明对我非常有帮助的一般性建议:我建议将所有包含预定计时器的属性声明为 weak
,因为它们由运行 循环。这样,您不需要在使它们无效后将它们显式设置为 nil
,而是每次您想要摆脱它时只需调用 invalidate
,它也会自动变为 [=16] =] 一旦它被 运行 循环触发,释放它可能持有的所有数据。
请注意,这仍然需要您调用 invalidate
以防您想要取消计时器或在更换计时器之前调用,但在这样做之后您不再需要将其设置为 nil
。