UITableView中存在多个倒计时Timer的一种处理办法

Github的完整项目源码:https://github.com/FourOnes/seckill

在某些场景, 可能大部分在电商系统中,iOS端应用需要使用UITableView展示从后端拉取的商品(活动)数据信息,包括名称、图片、以及截止时间等。

当前需要在每一个商品(活动)后面加一个时间倒计时,只有倒计时结束以后,用户才可以点击操作。比如在抢购商品的时候,一般都会有一个开始时间,在这之前一般都一个倒计时。在这样的情况下,UITableView有可能会展示后端成千上百的数据,如果简单高效的处理每一个商品(活动)的倒计时。

为了简化,只有倒计时结束以后,才可以点击ORDER。

整体思路

如果有一千条数据要展示,不可能为每一个数据开启一个Timer启动倒计时。

每一个产品都有一个截止时间的字段,自定义UITableViewCell,将产品信息绑定到UITableViewCell。然后启动一个间隔周期为1秒的Timer,定期的向外面发送通知,同时UITableViewCell订阅这个通知,根据当前的时间与截止时间,可以计算出还剩余的时间,如果剩余时间为0,则显示ORDER按钮。

这里利用了UITableView的重用机制,比如设备当前可见区域可以显示8个UITableViewCell,那么在整个生命周期中最大存在8个UITableViewCell示例。

核心代码

TimerManager

主要维护一个Timer的启动停止

#import 
extern NSString * const timerManagerNotify;
@interface TimerManager : NSObject
+(TimerManager *)manager;
-(void)start;
-(void)stop;
@end

#import "TimerManager.h"

static TimerManager *staticTimeManager;
NSString * const timerManagerNotify = @"com.limingru.timermanager";

@interface TimerManager()
@property(nonatomic,strong)NSTimer *timer;
@end

@implementation TimerManager
+(TimerManager *)manager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        staticTimeManager = [TimerManager new];
    });
    return staticTimeManager;
}
-(void)start {
    if (self.timer) return;
    self.timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
-(void)stop {
    [self.timer invalidate];
    self.timer.fireDate = [NSDate distantFuture];
    self.timer = nil;
}

-(void)timerAction {
    NSLog(@"TimerManager timerAction");
    [[NSNotificationCenter defaultCenter] postNotificationName:timerManagerNotify object:nil];
}
@end

MyUITableViewCell

自定义的UITableViewCell,主要订阅TimerManager发布的通知,更新界面

#import 
#import "Product.h"



@interface MyUITableViewCell : UITableViewCell
@property(nonatomic,strong)Product *product;
@end

#import "MyUITableViewCell.h"
#import "TimerManager.h"

@interface MyUITableViewCell()
@property (weak, nonatomic) IBOutlet UIButton *goBtn;
@property (weak, nonatomic) IBOutlet UILabel *statusLbl;
@property (weak, nonatomic) IBOutlet UILabel *timerLbl;

@end

@implementation MyUITableViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
    [self.goBtn setTitle:@"ORDER" forState:UIControlStateNormal];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(timeNotify:) name:timerManagerNotify object:nil];
}

-(void)setProduct:(Product *)product {
    _product = product;
    self.timerLbl.hidden = self.goBtn.hidden = YES;
    self.statusLbl.text = _product.name;
    [self checkTime];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    NSLog(@"dealloc >> %@",[self class]);
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (IBAction)go:(id)sender {
    NSLog(@"%@",[NSString stringWithFormat:@"ORDERED %@",self.product.name]);
}

-(void)timeNotify:(NSNotification *)sender {
    [self checkTime];
}

-(void)checkTime {
    NSDate *nowDate = [NSDate date];
    NSTimeInterval timeInterval = [nowDate timeIntervalSinceReferenceDate];
    NSTimeInterval diff = self.product.endTime - timeInterval;
    if (diff<=0) {
        self.timerLbl.hidden = YES;
        self.goBtn.hidden = NO;
        return;
    }
    self.timerLbl.hidden = NO;
    self.timerLbl.text = [NSString stringWithFormat:@"%.f",diff];
}


@end

完整源码地址

附上Github的完整项目源码:https://github.com/FourOnes/seckill

原文出处http://limingru.com/2018/06/42.html

你可能感兴趣的:(UITableView中存在多个倒计时Timer的一种处理办法)