如何在 Cocoa 中运行 NSTimer 直到标志变量 ON

Posted

技术标签:

【中文标题】如何在 Cocoa 中运行 NSTimer 直到标志变量 ON【英文标题】:How to run NSTimer until flag variable ON in Cocoa 【发布时间】:2013-09-04 03:48:02 【问题描述】:

我有一个问题:我想让 NSTimer 等到 FLAG 变量为 YES,如果 FLAG = YES,myTimer 将停止。我怎样才能做到这一点?我试过下面的代码:

NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:@selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer timerWithTimeInterval: delay
                                         target:self
                                       selector: @selector(resetAll:) userInfo:nil
                                        repeats:NO];
        [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
        [[NSApplication sharedApplication] runModalForWindow: scanningPanel];

这是resetAll()函数:

-(void) resetAll: (NSTimer *) theTimer

    if(FLAG)
    
        NSLog(@"killWindow");
        [[NSApplication sharedApplication] abortModal];
        [scanningPanel orderOut: nil];
        FLAG = NO;
    
    else
    
        delay +=6.0;
        myTimer= [NSTimer timerWithTimeInterval: delay
                                         target:self
                                       selector: @selector(resetAll:) userInfo:nil
                                        repeats:NO];
        [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
        [[NSApplication sharedApplication] runModalForWindow: scanningPanel];
    


我使用了 2 个 NSTimer,但只有 myTimer 运行,scanTimer 没有运行。请给我任何建议。提前致谢

【问题讨论】:

您想在升旗后立即结束计时器吗?如果是这种情况,您可能需要一个每秒或 500 毫秒重复的计时器,并在每个脉冲上检查标志或持续时间是否为真。 @TimothyWalters:是的,我想在升旗后立即结束计时器。你能给我示例代码吗?非常感谢 尝试不使用计时器:***.com/questions/149646/… 【参考方案1】:

为什么不使用键值观察来进行 FLAG 更改?将 flag 变量添加为您正在使用的类的属性:

@property(nonatomic, assign) BOOL flag;

为了避免在您的 .m 中出现重复位置:

#define kFooFlagKey @"flag"

覆盖 -setFlag:因此它符合 KVO:

-(void)setFlag:(BOOL)flag

    if (_flag == flag) 
        return;
    
    [self willChangeValueForKey:kFooFlagKey];
    _flag = flag;
    [self didChangeValueForKey:kFooFlagKey];

在类的初始值设定项中,添加 self 作为您要监控的键路径的观察者。在这种情况下,它将用于属性“flag”。

[self addObserver:self
   forKeyPath:kFooFlagKey
      options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
      context:NULL];

不要忘记删除类中的观察者'-dealloc:

[self removeObserver:self forKeyPath:kFooFlagKey];

创建重复触发的计时器(firingCallBack 是每次触发时调用的方法):

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.0f
                                                  target:self
                                                selector:@selector(firingCallBack)
                                                userInfo:nil
                                                 repeats:YES];

实现KVO观察方法:

-(void)observeValueForKeyPath:(NSString *)keyPath
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context

    if ([keyPath isEqualToString:kFooFlagKey]) 
        if (self.flag) 
           [self performSelector:@selector(resetAll) withObject:nil afterDelay:0.0f];
        
    

根据需要执行 -resetAll。当您通过访问器设置标志变量并且标志设置为YES时,它将被调用

【讨论】:

【参考方案2】:
Try like this:-

NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:@selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
                                         target:self
                                       selector: @selector(resetAll:) userInfo:nil
                                        repeats:NO];
[NSApp beginSheet:scanningPanel modalForWindow:[self window]
        modalDelegate:self
       didEndSelector:nil
          contextInfo:self];

- (void)resetAll:(NSTimer *)theTimer

    if (flag== YES)
    
    [NSApp endSheet:scanningPanel];
    [scanningPanel orderOut:self];
        flag=NO;
    
    else
    
   delay +=6.0;
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
                                         target:self
                                       selector: @selector(resetAll:) userInfo:nil
                                        repeats:NO];
    [NSApp beginSheet:scanningPanel modalForWindow:[self window]
        modalDelegate:self
       didEndSelector:nil
          contextInfo:self];
    

【讨论】:

谢谢,但我不想使用 beginSheet。我想将其显示为 NSwindow?我该怎么做?【参考方案3】:

您只需启动计时器(已安排)并使其以相对较高的频率重复,并在满足条件时停止。一个计时器可以充当两个计时器,如下所示:

- (void)startTimers 

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];


- (void)timerFired:(NSTimer *)timer 

    if (self.stopTimerA && self.stopTimerB) 
        [timer invalidate];
     else 
        if (!self.stopTimerA)
            [self timerAFired];
        if (!self.stopTimerB)
            [self timerBFired];
    


- (void)timerAFired 
    // this can be coded like it has it's own timer
    // we didn't pass the timer, so we can't invalidate it
    // to stop...
    self.stopTimerA = YES;


- (void)timerBFired 
    // same idea here

【讨论】:

您可以使用两个计时器,或者同一个计时器并在调用时调用两个方法。我会补充我的答案。

以上是关于如何在 Cocoa 中运行 NSTimer 直到标志变量 ON的主要内容,如果未能解决你的问题,请参考以下文章

ios子线程怎样能开启NSTimer

UIScrollView 在滚动时暂停 NSTimer

UIScrollView 暂停 NSTimer 直到滚动完成

睡眠后可可 NSTimer

Cocoa Touch:App运行机制 NSRunLoop, KVC, KVO, Notification, ARC

如何暂停/播放 NSTimer?