郑州iOS點

来源:互联网 发布:创建外键的sql语句 编辑:程序博客网 时间:2024/04/26 07:20

最近在跟一个新项目...

整个项目只有不到20个接口,而且做的是即时通讯,socket协议有不到20个命令,前端逻辑重的不要不要的...

为了能完成需求文档上关于延时逻辑的任务,我把各种定时器都给用上了...

1. NSTimer;
NSTimer是一种非常省事的定时器,但是好多猿都没躲过它的坑.

一号坑-----重复创建NSTimer;

有时候,我们在写方法的时候需要注意,避免重复创建,在设置属性了以后,多加个判断,像下面一样:

if (self.connectTimer == nil) {     
   self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(<##>) userInfo:@{<##>} repeats:YES];    
   [self.connectTimer fire];   

}  

而且建议我们尽量要将fire写在创建定时器方法外面:

- (void)timerFire {

      if ([_connectTimer isValid]) {
         [_connectTimer invalidate];
      }

      [self.connectTimer fire];

     }  

二号坑-----清除NSTimer;  

清除和暂停是两回事,一旦再次调用,就会发现定时器会跑不止一遍,正确严谨的销毁NSTimer 的姿势应该是下面这样的:
- (void)shutDownTimer {
    if ([_connectTimer isValid]) {
        [_connectTimer invalidate]; 
    }
    _connectTimer =nil;
}

这样,我们就可以在任何地方创建,启动,销毁NSTimer了;


2.GCD;

  GCD不用多说了吧,验证码倒计时最经典的使用方法了 

__block int timeout = 60; //倒计时时间
                    
                    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
                    
                    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
                    
                    dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
                    
                    dispatch_source_set_event_handler(_timer, ^{
                        
                        if(timeout<=0){ //倒计时结束,关闭
                           
                            dispatch_source_cancel(_timer);
                            
                            dispatch_async(dispatch_get_main_queue(), ^{
                                
                                //设置界面的按钮显示 根据自己需求设置
                                [weakSelf.verificationCodeBtn setTitle:@"获取验证码" forState:UIControlStateNormal];
                                
                                [weakSelf.verificationCodeBtn setTitleColor:WHITE_COLOR forState:(UIControlStateNormal)];
                                
                                weakSelf.verificationCodeBtn.userInteractionEnabled = YES;
                              
                            });
                            
                        }else{
                            
                            int seconds = timeout % 60;
                            
                            NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
                            
                            dispatch_async(dispatch_get_main_queue(), ^{
                                
                                [UIView beginAnimations:nil context:nil];
                                
                                [UIView setAnimationDuration:1];
                                
                                [weakSelf.verificationCodeBtn setTitle:[NSString stringWithFormat:@"%@秒后重新发送",strTime] forState:UIControlStateNormal];
                               
                                [UIView commitAnimations];
                                
                                weakSelf.verificationCodeBtn.userInteractionEnabled = NO;
                                
                            });
                            
                            timeout--;
                            
                        }
                    });
                    
                    dispatch_resume(_timer);


3.CADisplayLink

这个方法很有意思,思来想去,写在动画里是最完美的,这里分享一个单波纹的layer动画的定时器写法;

- (void)startAnimation {

    CALayer *layer = [[CALayer alloc] init];

    layer.cornerRadius = 15;

    layer.frame = CGRectMake(0, 0, SCREEN_WIDTH, 30);
    
    UIColor *color = BASIC_COLOR;

    layer.backgroundColor = color.CGColor;

    [self.aniView.layer addSublayer:layer];
    
    CAMediaTimingFunction *defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
    
    _animaTionGroup = [CAAnimationGroup animation];

    _animaTionGroup.delegate = self;

    _animaTionGroup.duration = 4;

    _animaTionGroup.removedOnCompletion = YES;

    _animaTionGroup.timingFunction = defaultCurve;
    
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];

    scaleAnimation.fromValue = @0.0;

    scaleAnimation.toValue = @1.0;

    scaleAnimation.duration = 4;
    
    CAKeyframeAnimation *opencityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];

    opencityAnimation.duration = 4;

    opencityAnimation.values = @[@0.8,@0.4,@0];

    opencityAnimation.keyTimes = @[@0,@0.5,@1];

    opencityAnimation.removedOnCompletion = YES;
    
    NSArray *animations = @[scaleAnimation,opencityAnimation];

    _animaTionGroup.animations = animations;

    [layer addAnimation:_animaTionGroup forKey:nil];
    
    [self performSelector:@selector(removeLayer:) withObject:layer afterDelay:3];
}

- (void)removeLayer:(CALayer *)layer {

    [layer removeFromSuperlayer];

}

- (void)start {
    
    _disPlayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(delayAnimation)];
    
    _disPlayLink.frameInterval = 300;
    
    [_disPlayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
}

- (void)delayAnimation {
    
    [self startAnimation];
    
    [self updateTime];
    
}

- (void)stop {
    
    [self.aniView.layer removeAllAnimations];
    
    [_disPlayLink invalidate];
    
    _disPlayLink = nil;
    
    [_disPlayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];


}

4.performSelector:@selector(<##>) withObject:<##> afterDelay:<##>;

这个更好理解了,在多少秒后实现指定的方法,注意,这个方法苹果是想废弃的,因为确实可能会有内存管理上的问题;

所以,我们可能要用上取消performSelector:方法的方法:

取消指定的延时:


[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(<##>) object:nil];


取消全部延时:


[NSObject cancelPreviousPerformRequestsWithTarget:self];


  

0 0
原创粉丝点击