代码改变世界

iOS 高效开发-----延时执行用GCD

2015-05-20 16:23  PingKang  阅读(11313)  评论(0编辑  收藏  举报

早期我们使用延时执行的方法都是用NSObject 类提供的,performSelector:系列的方法,具体有哪些我们看一下

我们一般让某个对象延时执行某个方法都会调用包含  afterDelay这个参数的方法,此参数即代表延时多长时间执行 ,但是这一系列的方法的参数都只接受继承自NSObject类得对象,也就是说如果我们要向其中传入基本的数据类型,那就必须涉及到数据类型转换,这显然会增加开销,而且这一系列的方法最多也就能传如一个参数,如果我们要传多个参数怎么办呢 ,如果想继续使用这个方法,那我们就必须把多个参数写入数组或字典中去,然后把数组或字典对象传给这个方法,那么着就又会增加我们插入数组或字典,解析数组或字典的代码 ,数据量达到一定情况的话,这个开销是可想而知的,而且我们还要知道数组和字典中得每个对象都代表什么,很麻烦;

不过我们可以用块来解决这一问题 ,GCD 为我们提供了一个演示执行的块函数,其具体定义如下:

void dispatch_after ( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block );

我们在调用此方法的时候,系统也考虑的很周到,当我们写入dispatch_after时,这个完整的函数就会呈现出来,我们看一下

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });

调用很方便,如果我们想把里面的内容放到主线程中去运行的话,也很方便,例如:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [son study];
    });
});

 

还记得当时有一个问题,就是想给UIButton的点击事件加点料,让系统中的所有的按钮都禁止快速点击或者连击,当时问了看了好多博客,都没有好的解决方案,前篇一律的讨论或者建议,都是使用performSelector:afterDelay这种方法,但是这样的话,我还要实现另一个方法 。后来是这么解决的呢 ,这里再次引用我之前写的内容,重写父类函数,然后使用GCD的dispatch_after 方法解决;

具体实现如下:

//
//  CommonButton.h
//  CommonButton
//
//  Created by pk on 14/12/24.
//  Copyright (c) 2014年 pk. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface CommonButton : UIButton

@end

  

//
//  CommonButton.m
//  CommonButton
//
//  Created by pk on 14/12/24.
//  Copyright (c) 2014年 pk. All rights reserved.
//

#import "CommonButton.h"

@implementation CommonButton

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/


- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    [super sendAction:action to:target forEvent:event];
    self.enabled = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.enabled = YES;
    });
}

@end

  

这样的实现,很清楚,结构简明,使用简单,想使用此方法,只要将改一下类得继承就行;

 

总结:performSelector 系列方法所能处理的选择器太过于局限性了 ,选择器的返回值类型和参数的个数都会受到限制;

    而dispatch_after就没有这些问题,另外,如果想把任务放在另一个线程上执行,最好不要用performSelector系列方法,而应该把任务封装到块里,然后调用GCD的相关方法来实现就行