具有单独 timeleft 的多个 NSTimer

Posted

技术标签:

【中文标题】具有单独 timeleft 的多个 NSTimer【英文标题】:Multiple NSTimer with individual timeleft 【发布时间】:2014-10-17 09:14:45 【问题描述】:

我想编写一个创建多个 NSTimer 的方法(事先不会知道 nstimer 的数量,代码应该是通用的),它将调用一个方法作为其选择器,该方法将 timeleft 更新为其文本。基本上是倒计时。 现在对于许多计时器,必须存在许多标签,并且我已经在事先知道计时器 n 标签(相同)的数量时通过创建那么多 nstimer 及其每个 timeleft 作为实例变量对象来做到这一点。

但是每个计时器都有自己的剩余时间。 我的问题是 - 是否可以维护多个未知数量的 nstimer 来运行单个方法(所有计时器都调用该方法),其中每个计时器将有其单独的倒计时或剩余时间,关于计时器将运行多少次。 如果是这样,应该是什么逻辑。

【问题讨论】:

研究NSTimer上的userInfo属性 已经尝试过了,即使我将每个 NSTimer 的剩余时间作为其用户信息发送,它调用的方法也不知道它是从哪个定时器发送的。 我会使用一个计时器,它始终以 1 秒的间隔运行。然后在一个数组中维护各个“timeleft”值,可能带有指向相关文本字段的关联指针,并在 timer fire 方法的循环中执行 timeleft 递减和更新文本字段。这将更容易维护和更好地运行。 仍然没有解决问题,该方法不会知道它是从哪个特定的计时器瞬间被调用的,所以,我不能写一个通用代码来说明数组的索引它必须获取的倒计时数组。 单个计时器是最好的方法,但是如果您确实想要多个计时器,您需要做的就是在 userInfo 中存储一个 NSNumber 作为标签的索引。 【参考方案1】:

在“运行”计时器的对象中,保留一个始终运行的计时器对象和一个自定义对象列表,这些对象将维护要更新的“timeleft”和“label”实例:

标签时间.h:

@interface LabelTime : NSObject
@property NSTimeInterval timeLeft;
@property UILabel *label;
- (void)decrementTime:(NSTimeInteval)interval;
@end

标签时间.m:

@interface LabelTime

- (void)decrementTime:(NSTimeInterval)interval 
    NSTimeInterval newTimeLeft = self.timeLeft - interval;
    if (newTimeLeft >= 0.0) 
        self.label.text = [NSString stringWithFormat:@"%d seconds left", (int)newTimeLeft];
        // Only if you want whole numbers              ^^                ^^^^^
    
    self.timeLeft = newTimeLeft;


@end

someclass.m:

#define UPDATE_TIME 1.0

@implementation SomeClass () 
    NSTimer *_timer;
    NSTimeInterval _lastTimeFired;
    NSMutableArray *_labelTimes;     // array of LabelTime objects

- (void)_timerFired:(NSTimer *)timer;
@end

在某处初始化它们:

- (id)init 
    self = [super init];
    if (self) 
        _timer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_TIME
                                                  target:self
                                                selector:@selector(_timerFired:)
                                                userInfo:nil
                                                 repeats:YES];
        _lastTimeFired = [[NSDate date] timeIntervalSinceReferenceDate];
        _labelTimes = [NSMutableArray new];
    
    return self;


- (void)_timerFired:(NSTimer *)timer 
    NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
    NSTimeInterval interval = _lastTimeFired - now;
    for (LabelTime *labelTime in _labelTimes) 
        [labelTime decrementTime:interval];
    
    _lastTimeFired = now;

注意事项:

您可能希望“锁定”对_labelTimes 的读/写访问权限以确保线程安全。

【讨论】:

【参考方案2】:

好的,我解决了这个问题 我创建了一个数组,其中包含指向标签的指针,Droppy 建议。

这是我的 updateLabel 方法,由单个计时器调用。

(void)updateLabel
for(int i =0;i<[countdown count];i++)
int seconds,minute,hours,timeleft;
    timeleft = [[countdown objectAtIndex:i]intValue];
    NSLog(@"%i",timeleft);
seconds = timeleft%60;
minute = timeleft/60;
hours = minute /60;
    UILabel *mylabel = [labelArray objectAtIndex:i];
    mylabel.text = [NSString stringWithFormat:@"%i:%i:%i",hours,minute,seconds];
    timeleft --;
    NSLog(@"%@",countdown);
    [countdown replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%i",timeleft]];
     NSLog(@"%@",countdown);
if(timeleft ==0)
    [timer1 invalidate];



这是倒计时数组的内容

 countdown = [[NSMutableArray alloc]initWithObjects:@"1000" ,@"1523",@"234",@"600",@"900", nil];

希望这可以帮助其他面临类似问题的人

【讨论】:

以上是关于具有单独 timeleft 的多个 NSTimer的主要内容,如果未能解决你的问题,请参考以下文章

NSTimer 可以采用多个选择器吗?

如何为多个不同的控制器制作 NSTimer?迅速

页面实现多个定时器(计时器)时选用NSTimer还是GCD

重复 NSTimer、弱引用、拥有引用还是 iVar?

页面实现多个定时器(计时器)时选用NSTimer还是GCD?(干货不湿)

ios子线程怎样能开启NSTimer