ios - 在任何滚动或表格重新加载后,在 TableView 中使用计时器重新创建计时器

标签 ios objective-c xcode uitableview countdown

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

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

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

感谢任何帮助,

埃利亚斯

最佳答案

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

我建议放弃该类(class),并创建您自己的类(class)。实现这样的目标实际上很容易。

  1. 创建一个保存标题和结束日期的新类
  2. 将该类的实例存储在支持您的表的模型中
  3. 创建一个刷新tableView的NSTimer
  4. 设置您的单元格。

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

@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

enter image description here

关于ios - 在任何滚动或表格重新加载后,在 TableView 中使用计时器重新创建计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23193087/

相关文章:

ios - 如何在 Objective-C 中转换一个间接指针

objective-c - MagicalRecord插入太慢

ios - 如何在 Swift 中使用 GTMAppAuth

ios - 将 UILabel 的某些部分变成 UIButton?

ios - 使用函数类型或闭包来动态调用函数

iphone - 配置构建阶段的编译源

xcodebuild 标志覆盖 pods 项目目标的代码签名

ios - 如何使用 Titanium 检索用户的 iOS 版本

objective-c - 变量不可赋值(缺少 __block 类型说明符)

objective-c - NSNumberFormatter 不允许十进制输入