2012-02-24 74 views
1

我在使用NSTimer时遇到问题。 假设我有这样的结构: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 
    } 
} 

因此,让我们假设类ALLOC它的用户,并在之后将其释放。我的计时器仍然活着,对象也一样(因为定时器有保留)。 当计时器启动时,它会执行[self launchAThread],然后计时器将自动失效并释放它,并释放我的对象,该对象现在有一个retainCount = 0 ...让我们再假设一次该对象被释放后,这将导致崩溃,我无法做到阻止它进入我脑海。

我同意,这是很多假设,但我很想知道是否有人已经有这个问题,他是如何解决它的。

感谢您的阅读,我希望我很清楚! :)

回答

0

因为我正在做一个图书馆,我不能假设用户将调用清理功能任何时候。

因此,为了解决我的问题,我添加了一个新的“层”:一个新的类,将执行线程和计时器部分,以便我是这个类的用户,我知道我必须清理!

1

哟必须始终使您的计时器释放它之前无效。如果计时器是视图控制器的一部分,我总是在viewWillDisappear中使其无效。对我来说非常奇怪的是,NSTimers保留了他们的主人。我认为最好的方法是创建 - (void)cleanUp方法,它将使计时器失效并警告类的用户始终在发布之前使用cleanUp。如果有人知道更好的方式,我会很高兴。

+0

是的就是这样我现在正在做。但是就你而言,我想知道另一种方法,如果有的话)。无论如何感谢 – delannoyk 2012-02-24 17:05:26

+0

由于我正在创建一个库,我不能认为用户会随时调用cleanUp函数。所以为了解决我的问题,我添加了一个新层:一个新的类,它将执行线程和计时器部分,以便我是这个类的用户,并且我知道我必须进行清理! – delannoyk 2012-02-27 17:00:10

0

只要你不使用重复计时器,为什么不使用dispatch_after?您可以节省NSTimer对象的头痛和头顶。如果你坚持使用GCD,你也可以避免拨打detachNewThreadSelector:

0

NSRunloop将保留对您的计时器,这意味着你没有保留/释放它在所有

+0

真的不是我的问题。不过谢谢 – delannoyk 2012-02-25 09:20:22

0

我第一次使用cleanUp类功能。 我也有一个对象一个拥有对象B,它包含定时器 - 它保留了对象B.当对象A被释放时,它释放对象B,但B因为定时器保留它而继续生存。然后在解雇的方法,但计时器,我使用委托关系回调对象A→硬崩溃。这是对象A需要“清理”B的计时器的地方。这可能会导致其他问题,虽然如果其他对象也依赖于对象B.而且类A不应该也不可能知道类B的实现秘诀:-PI猜想一个好的解决方案可能是取消设置代理关系在释放之前是在A的dealloc中完成的,因为即使你释放它也不知道B是否会死亡 - 其他人可能保留了它(像D *** NSTIMER)... :-P