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


    早期我们使用延时执行的方法都是用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的相关方法来实现就行

  • 相关阅读:
    学习笔记之正向代理和反向代理的区别
    PHP程序员的进阶之路
    go语言笔记——切片函数常见操作,增删改查和搜索、排序
    golang的垃圾回收(GC)机制
    堆栈的详细讲解
    springAop必导jar包
    sring框架的jdbc应用
    下载jar包方法
    mysql数据乱码
    Eclipse打包java工程
  • 原文地址:https://www.cnblogs.com/tianlin106/p/4517483.html
Copyright © 2020-2023  润新知