保留重复的NSTimer以便以后访问? [英] Retaining repeating NSTimer for later access?

查看:106
本文介绍了保留重复的NSTimer以便以后访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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>


  1. NSTimer(Autorelease对象,不属于我)

  2. setWalkTimer +1)

  3. 发布(放弃我的拥有权,retainCount-1)

  4. 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:

  1. NSTimer (Autorelease object, not owned by me)
  2. setWalkTimer (takes ownership for me, retainCount+1)
  3. release (relinquishes my ownership, retainCount-1)
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆