我在控制台中收到此异常:
错误:
2015-06-25 23:12:01.841 Mac版复制[9512:584232] - [_ NSViewLayoutAux invalidate]:无法识别的选择器发送到实例0x6000001657c0
检查我的计时器是否有效/何时使其无效。
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;
我在使用zombie对象进行调试时出现此错误。
2015-06-26 00:39:45.523 Mac版复制[11191:824502] *** - [CFRunLoopTimer release]:发送到解除分配的实例0x608000175e40的消息
答案 0 :(得分:1)
这里有几个潜在的问题。
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
,它也会自动成为nil
{1}}一旦它被运行循环触发,释放它可能保留的所有数据。
请注意,如果您要取消定时器或更换定时器之前仍需要调用invalidate
,但在执行此操作后您不再需要将其设置为nil
。
答案 1 :(得分:0)
使其无效后,您应将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];
}
答案 2 :(得分:0)
来自文档:
因为运行循环维护计时器,从角度来看 内存管理通常不需要保持对a的引用 计划完毕后的计时器。由于计时器作为一个传递 当您将其方法指定为选择器时,您可以使参数无效 在该方法中适当的重复计时器。在很多 但是,您还需要选择使...无效 计时器 - 甚至可能在它开始之前。在这种情况下,您需要保持 对计时器的引用,以便您可以向其发送无效 适当时留言。如果您创建一个未安排的计时器(请参阅 “非计划的计时器”),那么你必须保持强烈的参考 计时器(在引用计数环境中,你保留它)这样 在使用之前不会解除分配。
所以你应该让计时器弱而不是强