第二个NSTimer无法正常工作?

时间:2014-02-07 07:26:31

标签: ios objective-c nstimer

我以前只有一个NSTimer工作正常。我已经在我的runloop中添加了另一个NSTimer,因为现在我需要在延迟后重复调用两个函数。两种功能都有不同的延迟。我的代码如下。

self.now = [NSDate date] ;
    self.timer = [[NSTimer alloc] initWithFireDate:self.now
                                          interval:500
                                            target:self
                                          selector:@selector(Func1)
                                          userInfo:nil
                                           repeats:YES] ;

    self.runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
    [self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];


    //Second timer start here.its not working.The function 'func2' is not getting called

    self.now = [NSDate date] ;
    self.timer = [[NSTimer alloc] initWithFireDate:self.now
                                          interval:60
                                            target:self
                                          selector:@selector(Func2)
                                          userInfo:nil
                                           repeats:YES] ;

    self.runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
    [self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10000]];

第一个NSTimer仍然有效,但第二个NSTimer无效。

4 个答案:

答案 0 :(得分:3)

虽然你覆盖你的属性并不好(它不会影响计时器的运行能力,但它只是意味着当你设置第二个计时器时你丢弃对第一个计时器的引用,因此你失去了invalidate第一个计时器的能力,如果你需要这样做,关键问题是你正在调用runUntilDate。没有必要这样做,第一个runUntilDate阻止了第二个计时器的创建,因为viewDidLoad将不会超出第一个runUntilDate电话。

因此,删除对runUntilDate的两次调用,两个计时器都能正常工作。如果要保留对两个计时器的引用,请使用不同的属性来保存对两个计时器的引用,以便在不再需要它们时可以单独invalidate它们。 (当你不再需要它们时,invalidate这些很重要,因为它们对self有强烈的引用,这意味着你有一个“强大的参考周期”。)


您可以简化代码示例:

NSDate *date = [NSDate date];

self.timer1 = [[NSTimer alloc] initWithFireDate:date
                                       interval:500
                                         target:self
                                       selector:@selector(method1:)
                                       userInfo:nil
                                        repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:self.timer1 forMode:NSRunLoopCommonModes];

self.timer2 = [[NSTimer alloc] initWithFireDate:date
                                       interval:60
                                         target:self
                                       selector:@selector(method2:)
                                       userInfo:nil
                                        repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:self.timer2 forMode:NSRunLoopCommonModes];

或者,除非你真的需要NSRunLoopCommonModes,否则你可以这样做:

self.timer1 = [NSTimer scheduledTimerWithTimeInterval:500
                                               target:self
                                             selector:@selector(method1:)
                                             userInfo:nil
                                              repeats:YES];

self.timer2 = [NSTimer scheduledTimerWithTimeInterval:60
                                               target:self
                                             selector:@selector(method2:)
                                             userInfo:nil
                                              repeats:YES];

请注意,我正在使用带参数的方法(因此带有选择器的冒号):

- (void)method1:(NSTimer *)timer
{
    // do whatever
}

- (void)method2:(NSTimer *)timer
{
    // do whatever
}

答案 1 :(得分:2)

您必须声明NSTimer的第二个属性。目前,在执行此操作时,您将覆盖第一个计时器

self.timer = [[NSTimer alloc] initWithFireDate:self.now
                                      interval:60
                                        target:self
                                      selector:@selector(Func2)
                                      userInfo:nil
                                       repeats:YES] ;

在您的界面中声明timer2与您的计时器声明类似,并使用self.timer2存储第二个计时器。

答案 2 :(得分:0)

实际上runUntilDate会导致应用程序继续运行计时器,之后的语句将不会被执行。试试这个:

 self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
                                      interval:500
                                        target:self
                                      selector:@selector(Func1)
                                      userInfo:nil
                                       repeats:YES] ;

self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];


//Second timer start here.its not working.The function 'func2' is not getting called

self.now = [NSDate date] ;
self.timer = [[NSTimer alloc] initWithFireDate:self.now
                                      interval:60
                                        target:self
                                      selector:@selector(Func2)
                                      userInfo:nil
                                       repeats:YES] ;

self.runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];

即使您对两个计时器使用相同的timer变量,它也会起作用。但正如其他答案所指出的那样,你失去了使第一个计时器无效的能力。只需注释掉这两个地方的runUntilDate语句。

答案 3 :(得分:0)

为您的计时器声明第二个属性不是解决方案。你只需要使旧计时器无效并在主线程上分配新的计时器就可以了!试试这个:

   dispatch_async(dispatch_get_main_queue(), ^{
    _timer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                     target:self
                                                   selector:@selector(function:)
                                                   userInfo:nil
                                                    repeats:YES];
    [_timer fire];
   });