美文网首页
UICollectionViewCell、UITableView

UICollectionViewCell、UITableView

作者: extremebin | 来源:发表于2016-07-23 10:09 被阅读0次
collectionViewcell 写的活动促销倒计时
问题描述 :###

在屏幕滚动的时候,倒计时NSTimer 停止,滚动停止后,倒计时继续,这样就造成了时间差。

解决方案 :###

<p>先贴代码:</p>

#import <UIKit/UIKit.h>
#import "TimeCutView.h"
#import "ShopModel.h"
@interface ShopCell : UICollectionViewCell
//倒计时背景
@property (nonatomic,strong)UIImageView *timeBak;
//倒计时view
@property (nonatomic,strong) TimeCutView *countDown;

@end

@implementation ShopCell

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        _countDown= [TimeCutView countDown];
        _timeBak = [[UIImageView alloc]initWithFrame:CGRectMake(0, _specialImg.frame.size.height-30, _specialImg.frame.size.width, 30)];
        _timeBak.image = [UIImage imageNamed:@"daojishibg"];
        
        UILabel *timeCutLabel = [[UILabel alloc]initWithFrame:CGRectMake(5, 0, 85, 30)];
        timeCutLabel.text = @"距结束还有:";
        timeCutLabel.textColor = [UIColor whiteColor];
        timeCutLabel.font = [UIFont systemFontOfSize:13];
        
        _countDown = [[TimeCutView alloc]init];
        _countDown.frame = CGRectMake(75, 0, 100, 30);
        [self addSubview:timeCutLabel];
        [self addSubview:_countDown];
        [self addSubview:_timeBak];
    }
    return self;
}
@end

#import <UIKit/UIKit.h>
typedef void(^TimerStopBlock)();

@interface TimeCutView : UIView
// 时间戳
@property (nonatomic,assign)NSInteger timestamp;
// 背景
@property (nonatomic,copy)NSString *backgroundImageName;
// 时间停止后回调
@property (nonatomic,copy)TimerStopBlock timerStopBlock;
@property (nonatomic,strong) UILabel *separateLabel;
/**
 *  创建单例对象
 */
+ (instancetype)shareCountDown;// 工程中使用的倒计时是唯一的
/**
 *  创建非单例对象
 */
+ (instancetype)countDown; // 工程中倒计时不是唯一的
@end
#import "TimeCutView.h"
// label数量
#define labelCount 3
#define separateLabelCount 2
#define padding 6
@interface TimeCutView (){
    // 定时器
    NSTimer *timer;
}
@property (nonatomic,strong)NSMutableArray *timeLabelArrM;
@property (nonatomic,strong)NSMutableArray *separateLabelArrM;
// day
@property (nonatomic,strong)UILabel *dayLabel;
// hour
@property (nonatomic,strong)UILabel *hourLabel;
// minues
@property (nonatomic,strong)UILabel *minuesLabel;
// seconds
@property (nonatomic,strong)UILabel *secondsLabel;
@end

@implementation TimeCutView

// 创建单例
+ (instancetype)shareCountDown{
    static id instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[TimeCutView alloc] init];
    });
    return instance;
}

+ (instancetype)countDown{
    return [[self alloc] init];
}

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        [self addSubview:self.dayLabel];
        [self addSubview:self.hourLabel];
        [self addSubview:self.minuesLabel];
        [self addSubview:self.secondsLabel];
        
        for (NSInteger index = 0; index < separateLabelCount; index ++) {
            _separateLabel = [[UILabel alloc] init];
            _separateLabel.text = @":";
            _separateLabel.textAlignment = NSTextAlignmentCenter;
            _separateLabel.textColor = [UIColor whiteColor];
            _separateLabel.font = [UIFont systemFontOfSize:13];
            [self addSubview:_separateLabel];
            [self.separateLabelArrM addObject:_separateLabel];
        }
    }
    return self;
}

- (void)setBackgroundImageName:(NSString *)backgroundImageName{
    
}

// 拿到外界传来的时间戳
- (void)setTimestamp:(NSInteger)timestamp{
    _timestamp = timestamp;
    if (_timestamp != 0) {
        timer =[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timer:) userInfo:nil repeats:YES];
        //##########################解决滑动时计时器停止###########################
        //    UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保
        //                     证界面滑动时不受其他 Mode 影响(操作 UI 界面的情况下运行)
        //    NSRunLoopCommonModes :这是一个占位用的 Mode,不是一种真正的 Mode
        //                     (RunLoop无法启动该模式,设置这种模式下,默认和操作 UI
        //                     界面时线程都可以运行,但无法改变 RunLoop 同时只能在一种
        //                     模式下运行的本质)
        //        NSDefaultRunLoopMode : App 的默认 Mode,通常主线程是在这个 Mode
        //                     下运行(默认情况下运行)
        //##########################解决滑动时计时器停止###########################
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
}

-(void)timer:(NSTimer*)timerr{
    _timestamp--;
    [self getDetailTimeWithTimestamp:_timestamp];
    if (_timestamp == 0) {
        [timer invalidate];
        timer = nil;
        // 执行block回调
        self.timerStopBlock();
    }
}

- (void)getDetailTimeWithTimestamp:(NSInteger)timestamp{
    NSInteger ms = timestamp;
    NSInteger ss = 1;
    NSInteger mi = ss * 60;
    NSInteger hh = mi * 60;
    NSInteger dd = hh * 24;
    
    // 剩余的
    NSInteger day = ms / dd;// 天
    NSInteger hour = (ms - day * dd) / hh;// 时
    NSInteger minute = (ms - day * dd - hour * hh) / mi;// 分
    NSInteger second = (ms - day * dd - hour * hh - minute * mi) / ss;// 秒
    //    NSLog(@"%zd日:%zd时:%zd分:%zd秒",day,hour,minute,second);
    
    if (day == 0) {
        // 获得view的宽、高
        CGFloat viewW = self.frame.size.width;
        CGFloat viewH = self.frame.size.height;
        // 单个label的宽高
        CGFloat labelW = viewW / labelCount;
        CGFloat labelH = viewH;
        self.dayLabel.text = @"";
        [self.hourLabel setFrame:CGRectMake(0, 0, labelW, labelH)];
        [self.minuesLabel setFrame:CGRectMake(labelW, 0, labelW, labelH)];
        [self.secondsLabel setFrame:CGRectMake(2 * labelW , 0, labelW, labelH)];
        for (NSInteger index = 0; index < self.separateLabelArrM.count ; index ++) {
            _separateLabel = self.separateLabelArrM[index];
            [_separateLabel setFrame: CGRectMake((labelW - 1) * (index + 1), 0, 5, labelH)];
        }
        self.hourLabel.text = [NSString stringWithFormat:@"%zd时",hour];
        self.minuesLabel.text = [NSString stringWithFormat:@"%zd分",minute];
        self.secondsLabel.text = [NSString stringWithFormat:@"%zd秒",second];
    }else{
        self.dayLabel.text = [NSString stringWithFormat:@"%zd天",day];
        self.hourLabel.text = [NSString stringWithFormat:@"%zd时",hour];
        self.minuesLabel.text = [NSString stringWithFormat:@"%zd分",minute];
        self.secondsLabel.text = [NSString stringWithFormat:@"%zd秒",second];
    }
    
    
}

- (void)layoutSubviews{
    [super layoutSubviews];
    // 获得view的宽、高
    CGFloat viewW = self.frame.size.width;
    CGFloat viewH = self.frame.size.height;
    // 单个label的宽高
    CGFloat labelW = viewW / labelCount;
    CGFloat labelH = viewH;
    self.dayLabel.frame = CGRectMake(0, 0, labelW, labelH);
    self.hourLabel.frame = CGRectMake(labelW, 0, labelW, labelH);
    self.minuesLabel.frame = CGRectMake(2 * labelW , 0, labelW, labelH);
    self.secondsLabel.frame = CGRectMake(3 * labelW, 0, labelW, labelH);
    
    for (NSInteger index = 0; index < self.separateLabelArrM.count ; index ++) {
        _separateLabel = self.separateLabelArrM[index];
        _separateLabel.frame = CGRectMake((labelW - 1) * (index + 2), 0, 5, labelH);
    }
}


#pragma mark - setter & getter

- (NSMutableArray *)timeLabelArrM{
    if (_timeLabelArrM == nil) {
        _timeLabelArrM = [[NSMutableArray alloc] init];
    }
    return _timeLabelArrM;
}

- (NSMutableArray *)separateLabelArrM{
    if (_separateLabelArrM == nil) {
        _separateLabelArrM = [[NSMutableArray alloc] init];
    }
    return _separateLabelArrM;
}

- (UILabel *)dayLabel{
    if (_dayLabel == nil) {
        _dayLabel = [[UILabel alloc] init];
        _dayLabel.textAlignment = NSTextAlignmentCenter;
        _dayLabel.textColor = [UIColor whiteColor];
        _dayLabel.font = [UIFont systemFontOfSize:13];
    }
    return _dayLabel;
}

- (UILabel *)hourLabel{
    if (_hourLabel == nil) {
        _hourLabel = [[UILabel alloc] init];
        _hourLabel.textAlignment = NSTextAlignmentCenter;
        _hourLabel.textColor = [UIColor whiteColor];
        _hourLabel.font = [UIFont systemFontOfSize:13];
    }
    return _hourLabel;
}

- (UILabel *)minuesLabel{
    if (_minuesLabel == nil) {
        _minuesLabel = [[UILabel alloc] init];
        _minuesLabel.textAlignment = NSTextAlignmentCenter;
        _minuesLabel.textColor = [UIColor whiteColor];
        _minuesLabel.font = [UIFont systemFontOfSize:13];
    }
    return _minuesLabel;
}

- (UILabel *)secondsLabel{
    if (_secondsLabel == nil) {
        _secondsLabel = [[UILabel alloc] init];
        _secondsLabel.textAlignment = NSTextAlignmentCenter;
        _secondsLabel.textColor = [UIColor whiteColor];
        _secondsLabel.font = [UIFont systemFontOfSize:13];
    }
    return _secondsLabel;
}


@end

在计时器中使用了NSRunLoop来解决时间停止的问题

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
// 在默认模式下添加的 timer 当我们拖拽 scrollerView 的时候,不会运行 run 方法
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 

// 在 UI 跟踪模式下添加 timer 当我们拖拽 scrollerView 的时候,run 方法才会运行 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode]; 

// timer 可以运行在两种模式下,相当于上面两句代码写在一起 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响(操作 UI 界面的情况下运行)
NSRunLoopCommonModes :这是一个占位用的 Mode,不是一种真正的 Mode (RunLoop无法启动该模式,设置这种模式下,默认和操作 UI 界面时线程都可以运行,但无法改变 RunLoop 同时只能在一种模式下运行的本质)
NSDefaultRunLoopMode : App 的默认 Mode,通常主线程是在这个 Mode 下运行(默认情况下运行)

文中引用了这位同学提供的相关知识<a href="http://www.jianshu.com/p/338594ec008f" title="">http://www.jianshu.com/p/338594ec008f</a>

相关文章

网友评论

      本文标题:UICollectionViewCell、UITableView

      本文链接:https://www.haomeiwen.com/subject/qatwjttx.html