tableview列表中的cell单元格有倒计时的情况处理

在项目开发中遇到在tableiview列表中的cell单元格要使用到倒计时功能,当处理不当时,即cell复用没使用好时,会出现倒计时显示异常。比如说第一个cell显示且倒计时开始后,当tableview列表向上滚动,即第一个cell向上移动且移出屏幕,然后tableview列表再向下滚动,即第一个cell向下移动且又在屏幕显示,这个时候你会发现倒计时又是从头开始计时了。

为了避免这种情况的产生,在编码过程中我们只需要这样考虑,并这样做就可以了


步骤1 自定义cell

1-1 在自定义cell中创建NSTimer进行倒计时(将每个cell中的倒计时在当前cell中进行)

1-2 在自定义cell中设置可以获取该NSTimer的方法(便于对NSTimer计时器的释放处理)

步骤2 在tableview列表所在视图viewcontroller中定义四变量

2-1 变量1 NSTimer(设置为当前视图中的计时器,用于进行倒计时计算时间间隔差)

2-2 变量2 NSMutableArray(用于保存每个计时器,便于当前视图释放时,处理计时器)

2-3 变量3 NSInteger(当前时间点,与变量4计算时间间隔差)

2-4 变量4 NSInteger(变化时间点,在变量1中进行自减,即倒计时计算;同时与变量3计算时间变化间隔差)

步骤3 使用

3-1 在tableview中使用

3-1-1 在cellForRow方法中执行自定义cell的倒计时方法

3-1-2 在cellForRow方法中获取自定义cell的计时器并保存在NSMutableArray中

3-2 在viewcontroller视图中使用

3-2-1 在viewWillDisapper方法中释放保存有计时器的数组


详见代码


1 自定义cell代码

1-1 .h文件

#import <UIKit/UIKit.h>


@interface CountDownCell : UITableViewCell

{

    @private

    UILabel *label;

    

    NSTimer *coundTimer;   // 计时器

    NSInteger currentTime; // 计时时间,秒

}


/// 开始计时

- (void)coundDownStart:(NSInteger)time;


/// 释放计时器

- (void)releaseTimer;


/// 获取计时器,便于释放计时器

- (NSTimer *)getCellTimer;


@end


1-2 .m文件

#import "CountDownCell.h"


@implementation CountDownCell


- (void)awakeFromNib {

    // Initialization code

}


- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

    [super setSelected:selected animated:animated];


    // Configure the view for the selected state

}


- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self)

    {

        self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        

        label = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, self.frame.size.width - 10.0 * 2, self.frame.size.height)];

        [self addSubview:label];

    }

    return self;

}


- (void)dealloc

{

    coundTimer = nil;

    NSLog(@"cell timer %@", coundTimer);

}


// 开始计时

- (void)coundDownStart:(NSInteger)time

{

    currentTime = time;

    [self show];

    if (!coundTimer)

    {

        coundTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(coundDown:) userInfo:nil repeats:YES];

    }

}


- (void)coundDown:(NSTimer *)timer

{

    currentTime--;

    [self show];

}


- (void)show

{

    NSInteger day = currentTime / (24 * 60 * 60);

    NSInteger hour = (currentTime % (24 * 60 * 60)) / (60 * 60);

    NSInteger minute = ((currentTime % (24 * 60 * 60)) % (60 * 60)) / 60;

    NSInteger second = ((currentTime % (24 * 60 * 60)) % (60 * 60)) % 60;

    NSString *time = [NSString stringWithFormat:@"%d%d%d分钟%d", day, hour, minute, second];

    NSString *timeStr = [NSString stringWithFormat:@"倒计时:%@", time];

    label.text = timeStr;

}


// 释放计时器

- (void)releaseTimer

{

    if (coundTimer)

    {

        if ([coundTimer isValid])

        {

            [coundTimer invalidate];

            coundTimer = nil;

        }

    }

}


/// 获取计时器

- (NSTimer *)getCellTimer

{

    return coundTimer;

}


@end



2 viewcontroller代码

2-1 .h文件

#import <UIKit/UIKit.h>


@interface TableCountdownVC : UIViewController


@end



2-2 .m文件

#import "TableCountdownVC.h"

#import "CountDownCell.h"


@interface TableCountdownVC () <UITableViewDataSource, UITableViewDelegate>


@property (nonatomic, strong) UITableView *mainTableView;

@property (nonatomic, strong) NSMutableArray *mainArray;


@property (nonatomic, strong) NSMutableArray *timerArray; // 存储timer数组,便于释放计时器

@property (nonatomic, strong) NSTimer *mainTimer;         // 计时器,控制计时间隔


@property (nonatomic, assign) NSTimeInterval sourceTime;  // 时间初始点,与currtentTime的时间差为变化时间间隔

@property (nonatomic, assign) NSTimeInterval currtentTime;// 时间变化后时点,与sourceTime的时间差为变化时间间隔


@end


@implementation TableCountdownVC


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view.

    

    self.title = @"cell倒计时复用";

    

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"reload" style:UIBarButtonItemStyleDone target:self action:@selector(buttonClick:)];

    

    [self setlocalData];

    

    [self setUI];

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


- (void)loadView

{

    [super loadView];

    self.view.backgroundColor = [UIColor whiteColor];

}


- (void)viewWillDisappear:(BOOL)animated

{

    [super viewWillDisappear:animated];

    

    [self killTimer];

}


- (void)dealloc

{

    self.mainTimer = nil;

    NSLog(@"timer %@", self.mainTimer);

}


#pragma mark - 创建视图


- (void)setUI

{

    if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)])

    {

        [self setEdgesForExtendedLayout:UIRectEdgeNone];

    }

    

    self.mainTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];

    [self.view addSubview:self.mainTableView];

    self.mainTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

    self.mainTableView.backgroundColor = [UIColor lightTextColor];

    self.mainTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;

    self.mainTableView.delegate = self;

    self.mainTableView.dataSource = self;

}


#pragma mark - 数据


- (void)setlocalData

{

    if (self.mainArray)

    {

        [self.mainArray removeAllObjects];

    }

    else

    {

        self.mainArray = [NSMutableArray array];

    }


    NSDate *date = [NSDate date];

    self.currtentTime = [date timeIntervalSinceReferenceDate];

    self.sourceTime = self.currtentTime;

    for (int i = 0; i < 30; i++)

    {

        NSInteger time = arc4random() % (int)self.currtentTime + 1000;

        NSNumber *timeNumber = [NSNumber numberWithInteger:time];

        [self.mainArray addObject:timeNumber];

    }

    

    if (!self.timerArray)

    {

        self.timerArray = [NSMutableArray array];

    }

    else

    {

        [self killTimer];

    }

    

    if (self.mainTimer)

    {

        [self.mainTimer invalidate];

        self.mainTimer = nil;

    }

    self.mainTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(coundDown:) userInfo:nil repeats:YES];

    [self.timerArray addObject:self.mainTimer];

}


- (void)killTimer

{

    if (self.timerArray)

    {

        for (NSTimer *subTimer in self.timerArray)

        {

            if (subTimer)

            {

                [subTimer invalidate];

            }

        }

        

        [self.timerArray removeAllObjects];

    }

}


#pragma mark - 响应事件


- (void)buttonClick:(UIButton *)button

{

    [self setlocalData];

    [self.mainTableView reloadData];

}


- (void)coundDown:(NSTimer *)timer

{

    self.currtentTime--;

}


#pragma mark - 列表视图


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    return self.mainArray.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *const reuseCell = @"reuseCell";

    CountDownCell *cell = (CountDownCell *)[tableView dequeueReusableCellWithIdentifier:reuseCell];

    if (!cell)

    {

        cell = [[CountDownCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseCell];

    }

    

    NSNumber *timeNumber = [self.mainArray objectAtIndex:indexPath.row];

    NSInteger time = timeNumber.integerValue;

    time = time - (self.sourceTime - self.currtentTime);

    [cell coundDownStart:time];

    

    NSTimer *cellTimer = [cell getCellTimer];

    [self.timerArray addObject:cellTimer];


    return cell;

}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

}




转载于:https://my.oschina.net/potato512/blog/647746

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值