使用NSTimer时遇到问题。 我们假设我有这种架构:
ThreadedClass.m(包含NSTimer *计时器;)
- (id) init {
if (self = [super init]) {
// do blablabla
[self launchAThread];
}
return self;
}
- (void) launchAThread {
[NSThread detachNewThreadSelector:@selector(selectorToMyThreadFunction)
toTarget:self
withObject:nil];
}
- (void) selectorToMyThreadFunction {
//I do my stuff in here
//Then i relaunch a Timer to call this function
//periodically but it has to be "atomic" so no
//repeating timer since i don't know the time
//this function will take
//I do some [self changeSomething];
[self restartTimer];
//MyThread ends here (and might be recreated by the Timer's bip
}
- (void)restartTimer {
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(restartTimer)
withObject:nil
waitUntilDone:NO];
return;
}
[timer invalidate];
[timer release];
timer = [[NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(launchWithTimer:)
userInfo:nil
repeats:NO] retain];
}
- (void) launchWithTimer:(NSTimer *)theTimer {
if (theTimer == timer)
{
[timer release];
timer = nil;
[self launchAThread];
}
else
{
//Nothing to be done in here, a user launch a thread manually
}
}
所以让我们假设类的用户分配它并在之后立即释放它。我的计时器仍然存在并且对象也是(因为计时器有保留)。
当计时器将触发时,它将执行[self launchAThread]
,然后计时器将使自身无效并释放它将释放我的对象,该对象现在具有retainCount = 0 ...让我们假设,再一次,对象被解除分配之后,这将导致崩溃,我无能为力阻止它出现在我脑海中。
我同意,这是很多假设,但我很想知道是否有人已经有这个问题以及他是如何解决的。
感谢阅读,我希望我很清楚! :)
答案 0 :(得分:1)
哟必须在释放之前始终使您的计时器无效。如果计时器是视图控制器的一部分,我总是在viewWillDisappear中使它失效。对我来说,奇怪的是NSTimers保留了他们的所有者。我认为最好的方法是创建 - (void)cleanUp方法,它将使计时器失效并警告类的用户在释放之前始终使用cleanUp。如果有人知道更好的方式,我会很高兴。
答案 1 :(得分:0)
只要你没有使用重复计时器,为什么不使用dispatch_after
?您将省去NSTimer对象的头痛和开销。如果你坚持使用GCD,你也可以避免拨打detachNewThreadSelector:
。
答案 2 :(得分:0)
NSRunloop将为您保留计时器,这意味着您根本没有保留/释放它
答案 3 :(得分:0)
由于我正在创建一个库,我不能假设用户会随时调用cleanUp函数。
所以为了解决我的问题,我添加了一个新的“层”:一个新的类,它将执行线程和计时器部分,这样我就是这个类的用户,我知道我必须清理它!
答案 4 :(得分:0)
我首先使用了一种cleanUp类型的功能。 我还有一个对象A拥有对象B,它包含定时器 - 它保留对象B.当对象A被释放时,它会释放对象B,但是B仍然存在,因为计时器保留了它。然后在方法中触发了但是计时器,我正在使用委托关系来回调对象A→硬崩溃。这是对象A需要“清理”B的计时器的地方。如果其他对象也依赖于对象B,这可能会导致其他问题。而且A类不应该也可能不知道B类的实现秘密。:-PI猜测一个好的解决方案可能是取消设置该委托发布之前的关系是在A的dealloc中完成的,因为你不知道即使你释放它也不会死B - 别人可能会保留它(就像D *** NSTIMER一样)... :-P < / p>