在tableview中使用timer会在任何滚动或表重新加载后重新创建计时器 [英] Using timer in a tableview re creates the timer after any scroll or table reload

查看:228
本文介绍了在tableview中使用timer会在任何滚动或表重新加载后重新创建计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 https://github.com/mineschan/MZTimerLabel/
并在我的Tableview中cellForRowAtIndex使用如下所示的计时器:

I'm using https://github.com/mineschan/MZTimerLabel/ and in my Tableview cellForRowAtIndex using the timer like below:

UILabel *lblTimer=(UILabel *)[cell viewWithTag:10];
MZTimerLabel *UpgradeTimer = [[MZTimerLabel alloc] initWithLabel:lblTimer andTimerType:MZTimerLabelTypeTimer];
[UpgradeTimer setCountDownTime:timestamp];
[UpgradeTimer startWithEndingBlock:^(NSTimeInterval timestamp) {
lblTimer.text = @"✔";
}];

但是在任何表重新加载或滚动之后,计时器表现得很奇怪,似乎它会重新生成多个计时器在同一个地方计数。
如何在使用此计时器时修复此问题?

But after any table reloading or scrolling, the timer behaves strange and seems it re-generates multiple timers for counting in the same place. How should I fix this while using this timer?

感谢任何帮助,

Elias

推荐答案

我查看了 MZTimerLabel ,它严重违反了MVC。它将属于模型的东西(计算时间的计时器)放入视图中。这就是你的问题来自哪里。应该能够重新创建视图而不会对模型产生副作用。

I had a look at MZTimerLabel, and it violates MVC badly. It puts something that belongs into the model (the timer that count's down the time) into the view. That is where your problem comes from. Views should be able to be recreated without having side effects on the model.

我建议抛弃那个课程,并创建自己的课程。实际上很容易实现这样的目标。

I would recommend to ditch that class, and create your own. It's actually quite easy to achieve something like this.


  1. 创建一个保存标题和结束日期的新类

  2. 将该类的实例存储在支持表格的模型

  3. 创建一个 NSTimer,刷新tableView

  4. 设置单元格。

  1. Create a new class that saves a title and a endDate
  2. Store instances of that class in the model that backs your table
  3. Create one NSTimer that refreshes the tableView
  4. Set up your cells.

这基本上是表格中基本倒计时所需的所有代码。因为它不会在视图中存储任何数据,所以您可以根据需要滚动:

That's basically all the code you need for a basic countdown in a table. Because it does not store any data in the view you can scroll as much as you like:

@interface Timer : NSObject
@property (strong, nonatomic) NSDate *endDate;
@property (strong, nonatomic) NSString *title;
@end

@implementation Timer
@end

@interface MasterViewController () {
    NSArray *_objects;
    NSTimer *_refreshTimer;
}
@end

@implementation MasterViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *modelStore = [NSMutableArray arrayWithCapacity:30];
    for (NSInteger i = 0; i < 30; i++) {
        Timer *timer = [[Timer alloc] init];
        timer.endDate = [NSDate dateWithTimeIntervalSinceNow:i*30];
        timer.title = [NSString stringWithFormat:@"Timer %ld seconds", (long)i*30];
        [modelStore addObject:timer];
    }
    _objects = modelStore;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [_refreshTimer invalidate]; // timer should not exist, but just in case.
    _refreshTimer = [NSTimer timerWithTimeInterval:0.5f target:self selector:@selector(refreshView:) userInfo:nil repeats:YES];

    // should fire while scrolling, so we need to add the timer manually:
    [[NSRunLoop currentRunLoop] addTimer:_refreshTimer forMode:NSRunLoopCommonModes];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [_refreshTimer invalidate];
    _refreshTimer = nil;
}

- (void)refreshView:(NSTimer *)timer {
    // only refresh visible cells
    for (UITableViewCell *cell in [self.tableView visibleCells]) {
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        [self configureCell:cell forRowAtIndexPath:indexPath];
    }
}

#pragma mark - Table View

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _objects.count;
}

- (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    Timer *timer = _objects[indexPath.row];
    cell.textLabel.text = timer.title;
    NSInteger timeUntilEnd = (NSInteger)[timer.endDate timeIntervalSinceDate:[NSDate date]];
    if (timeUntilEnd <= 0) {
        cell.detailTextLabel.text = @"Finished";
    }
    else {
        NSInteger seconds = timeUntilEnd % 60;
        NSInteger minutes = (timeUntilEnd / 60) % 60;
        NSInteger hours = (timeUntilEnd / 3600);
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)hours, (long)minutes, (long)seconds];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    [self configureCell:cell forRowAtIndexPath:indexPath];
    return cell;
}

@end

这篇关于在tableview中使用timer会在任何滚动或表重新加载后重新创建计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆