保留重复的NSTimer以便以后访问? [英] Retaining repeating NSTimer for later access?
问题描述
我在 createTimer
方法中创建一个NSTimer,我想在后面的 cancelTimer
方法中引用。为了方便这一点,我通过保留属性取得NSTimer的所有权,以便我以后可以参考。让我困惑的问题是,如果我启动计时器,取消它,再次启动代码崩溃。
@property (非原子,保留)NSTimer * walkTimer;
。
<$ cntc:nt重复次数:YES];返回值为0,否则返回null。
[self setWalkTimer:tempTimer];
}
- (void)cancelTimer {
[walkTimer release];
[[self walkTimer] invalidate];
}
现在我似乎已经通过将cancelTimer更改为:
- (void)cancelTimer {
[self setWalkTimer:nil];
[[self walkTimer] invalidate];
}
我只是想知道为什么发布不工作,我的理解是: / p>
- NSTimer(Autorelease对象,不属于我)
- setWalkTimer +1)
- 发布(放弃我的拥有权,retainCount-1)
- invalidate(让系统处理计时器)
编辑:
/ this failed ...
- (void)cancelTimer {
[[self walkTimer] invalidate];
[walkTimer release];
}
//这很好...
- (void)cancelTimer {
[[self walkTimer] invalidate];
[self setWalkTimer:nil];
}
EDIT:002
$ b
最初我认为我混淆了
@property(nonatomic,retain)NSTimer * walkTimer ;
//&
[self setWalkTimer];
并认为我需要一个版本来平衡属性,我不会覆盖它一个新的集合(要么对另一个对象或nil),并最终释放属性在dealloc。
属性(retain)
编辑:003
关于这个问题,我认为我个人感到困惑通过错误地使用 [walkTimer release]
结果主题漂移到一个新的问题,我写了 this
release
,然后再调用 invalidate
。这意味着,当您调用 invalidate
时,您已经放弃了计时器的所有权。实际上,您最终在取消分配的计时器实例上调用 invalidate
。
您应该做的是调用无效
之前您呼叫 release
。由于您使用的是保留属性,您只需将属性设置为 nil
:
//调度定时器。
self.walkTimer = [NSTimer scheduledTimerWith ...];
//取消定时器。
[self.walkTimer invalidate];
self.walkTimer = nil;
更新以清除有关内存管理的任何混淆
请务必记住内存管理规则 - 你拥有一个对象,如果你调用 alloc
, copy
或 retain
,如果你拥有一个对象,你必须最终调用 release
。在这种情况下, setWalkTimer:
保留计时器,因为该属性声明为 retain
- 这意味着您拥有计时器,必须在路上沿着释放
。 invalidate
方法不计为放弃计时器的所有权。
调度定时器,运行循环保留它,并且当定时器触发或无效时,运行循环释放它。但是,真的,你不需要知道 - 这是一个实现细节。通过 invalidate
调用 release
只是为了平衡 retain
当计时器在运行循环上计划时。
I am creating an NSTimer in the createTimer
method that I want to refer back to in the later cancelTimer
method. To facilitate this I am taking ownership of the NSTimer via a retained property so that I can refer back to it later. The issue that is confusing me is, if I start the timer, cancel it and start it again the code crashes.
@property(nonatomic, retain) NSTimer *walkTimer;
.
-(void)createTimer {
NSTimer *tempTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTimerDisplay) userInfo:nil repeats:YES];
[self setWalkTimer:tempTimer];
}
-(void)cancelTimer {
[walkTimer release];
[[self walkTimer] invalidate];
}
Now I seem to have fixed this by changing cancelTimer to:
-(void)cancelTimer {
[self setWalkTimer:nil];
[[self walkTimer] invalidate];
}
I am just curious why release was not working, my understanding was that:
- NSTimer (Autorelease object, not owned by me)
- setWalkTimer (takes ownership for me, retainCount+1)
- release (relinquishes my ownership, retainCount-1)
- invalidate (lets system dispose of timer)
EDIT:
// this fails ...
-(void)cancelTimer {
[[self walkTimer] invalidate];
[walkTimer release];
}
// this works fine ...
-(void)cancelTimer {
[[self walkTimer] invalidate];
[self setWalkTimer: nil];
}
EDIT: 002
Initially I think I was mixing up
@property(nonatomic, retain) NSTimer *walkTimer;
// &
[self setWalkTimer];
and thinking that I needed a release to balance the property, I don't I either overwrite it with a new set (either to another object or nil) and finally release the property in dealloc.
Is the property(retain) the same as retain, I would say no, which is where I was going wrong I think.
EDIT: 003
With regards to this question I think I personally confused things by wrongly using [walkTimer release]
As a result the topic drifted to essentially a new question which I have written up as this
You release
before you call invalidate
. That means by the time you call invalidate
, you've already relinquished ownership of the timer. In practice, you end up calling invalidate
on a deallocated timer instance.
What you should do is call invalidate
before you call release
. Since you are using a retained property, you can just set the property to nil
:
// Schedule the timer.
self.walkTimer = [NSTimer scheduledTimerWith...];
// Cancel the timer.
[self.walkTimer invalidate];
self.walkTimer = nil;
Update to clear up any confusion regarding memory management
It's important to keep in mind the Memory Management Rules of Objective-C — you own an object if you call alloc
, copy
or retain
on it, and if you own an object, you have to eventually call release
. In this case, setWalkTimer:
retains the timer because the property is declared as retain
— that means you own the timer and must call release
on it down the road. The invalidate
method does not count as relinquishing ownership of the timer.
When you schedule a timer, the run loop retains it, and when the timer fires or is invalidated, the run loop releases it. But really, you don't need to know that — it's an implementation detail. The call to release
by invalidate
is only to balance the retain
when the timer was scheduled on the run loop.
这篇关于保留重复的NSTimer以便以后访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!