谈起iOS的dispatch(正式称谓是Grand Central Dispatch或GCD),不得不说这又是iOS(包括MacOSX)平台的创新,优缺点这里不讨论,只有当你使用时才能真正体会到。我们说dispatch函数的主要目的是实现多任务并发代码,那么要理解dispatch函数,先来了解dispatch对象的定义。

dispatch对象类型的部分定义,主要使用C语言的宏定义:

<os/object.h>文件:

#define OS_OBJECT_CLASS(name) OS_##name

#define OS_OBJECT_DECL(name, ...) \

@protocol OS_OBJECT_CLASS(name) __VA_ARGS__ \

@end \

typedef NSObject<OS_OBJECT_CLASS(name)> *name##_t

#define OS_OBJECT_DECL_SUBCLASS(name, super) \

OS_OBJECT_DECL(name, <OS_OBJECT_CLASS(super)>)

<dispatch/object.h>文件:

#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)

#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))

OS_OBJECT_DECL(dispatch_object); //定义dispatch_object_t

<dispatch/queue.h>文件(dispatch队列类定义,其它dispatch对象类似):

DISPATCH_DECL(dispatch_queue); //定义dispatch_queue_t

可以通过Xcode预编译后可以看到最终结果,最终定义的都是NSObject类,虽然它们之间没用直接继承关系,但都实现OS_dispatch_object接口,这样dispatch_queue_t对象也同样是dispatch_object_t的对象了。下面就是预编译dispatch_object_t和dispatch_queue_t的结果:

@protocol OS_dispatch_object

@end

typedef NSObject<OS_dispatch_object> *dispatch_object_t;

@protocol OS_dispatch_queue <OS_dispatch_object>

@end

typedef NSObject<OS_dispatch_queue> *dispatch_queue_t;

由于dispatch api接口定义成C函数的形式,dispatch的对象都是由C函数形式的厂方法得到(不能继承dispatch类,不用alloc),这样做隐藏dispatch对象的具体形态,把注意力放在如何调用dispatch api上。

从上面dispatch对象宏定义可以看到dispatch对象类的名称一般为dispatch_xyz_t(严格来讲是对象指针),它们都可以看成dispatch_object_t的子类(对象指针),所以使用dispatch对象时套用这个概念就行。

有关dispatch对象的基本接口如下:

void dispatch_retain(dispatch_object_t object); //替代dispatch对象常规的retain来持有对象,但ARC编程中不再允许

void dispatch_release(dispatch_object_t object); //替代dispatch对象常规的release来释放对象,同样ARC编程中不再允许

void dispatch_set_context(dispatch_object_t object, void *context); //给dispatch对象绑定特定数据对象(类似线程的TLS数据),会被传给dispatch对象的finalizer函数

void *dispatch_get_context(dispatch_object_t object); //返回dispatch对象绑定的数据对象指针

void dispatch_set_finalizer_f(dispatch_object_t object, dispatch_function_t finalizer); //设置dispatch对象的finalizer函数,当该对象释放时会调用finalizer,部分代码解释如何使用这个函数(ARC模式):

dispatch_object_t dispatchObject = ...;

void *context = ...;

dispatch_set_context(dispatchObject, context);

dispatch_set_finalizer_f(dispatchObject, finalizer);

......

dispatchObject = nil; //dispatchObject被释放,这时调用finalizer函数

......

void finalizer(void *context)

{

  //处理或释放context相关资源

}

 

dispatch对象的另外两个接口是:

void dispatch_resume(dispatch_object_t object); //激活(启动)在dispatch对象上的block调用,可以运行多个block

void dispatch_suspend(dispatch_object_t object); //挂起(暂停)在dispatch对象上的block调用,已经运行的block不会停止

一般这两个函数的调用必须成对,否则运行会出现异常。

至此你是否发现这两个函数有些与众不同呢?好像从来没有这么使用对象的,启动对象--暂停对象,呵呵。这正是理解dispatch对象的关键所在。dispatch对象其实是抽象的任务,把动态的任务变成对象来管理。任务是动态的,不存在继承关系,这就是为什么GCD没有提供静态继承dispatch对象类的方式。如果能这样理解,那么在使用dispatch函数时就能够更灵活地去编写代码,实现各种并发的多任务代码。

iOS多线程的初步研究(七)-- dispatch对象的更多相关文章

  1. iOS多线程的初步研究1

    iOS多线程的初步研究(一) 对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用.产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用. 一.显示调用的类为NS ...

  2. iOS多线程的初步研究(六)

    iOS多线程的初步研究(六) iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管 ...

  3. iOS多线程的初步研究3

    iOS多线程的初步研究(三) 弄清楚NSRunLoop确实需要花时间,这个类的概念和模式似乎是Apple的平台独有(iOS+MacOSX),很难彻底搞懂(iOS没开源,呜呜). 官网的解释是说run ...

  4. iOS多线程的初步研究

    iOS多线程的初步研究(四) 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NST ...

  5. iOS多线程的初步研究(一)-- NSThread

    对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用.产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用. 一.显示调用的类为NSThread.一般构造NSTh ...

  6. iOS多线程的初步研究(八)-- dispatch队列

    GCD编程的核心就是dispatch队列,dispatch block的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用.所以说,结合bloc ...

  7. iOS多线程的初步研究(九)-- dispatch源

    dispatch源(dispatch source)和RunLoop源概念上有些类似的地方,而且使用起来更简单.要很好地理解dispatch源,其实把它看成一种特别的生产消费模式.dispatch源好 ...

  8. iOS多线程的初步研究(十)-- dispatch同步

    GCD提供两种方式支持dispatch队列同步,即dispatch组和信号量. 一.dispatch组(dispatch group) 1. 创建dispatch组 dispatch_group_t ...

  9. iOS多线程的初步研究(六)-- NSOperation

    iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管理线程的运行,从而更加简洁地实 ...

随机推荐

  1. EMVTag系列13《脱机PIN》

    DGI8010用于个人化借记贷记交易中使用的脱机PIN.数据强制要求加密.制卡数据传输过程中,此DGI采用DEK加密保护. 数据分组标识 '8010'的数据内容       要求            ...

  2. oracle 日志文件管理

    OS: [root@b28-122 ~]# more /etc/oracle-releaseOracle Linux Server release 5.7 DB: SQL> select * f ...

  3. ios中怎么样自动剪切图片周围超出的部分

    UIImageView *image = [[UIImageView alloc] init]; image.clipsToBounds = YES;

  4. iOS学习之Object-C语言简单的通讯录管理系统

    用这几天学的OC的知识,写了一个实现简单功能的通讯录管理系统,在这里分享给大家: 通讯录管理系统 *  需求: 1.定义联系人类Contact.实例变量:姓名(拼音,首字母大写).性别.电话号码.住址 ...

  5. vhdl基础---分频

    偶数分频 ibrary IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_arith; use ieee.std_logic_unsigned ...

  6. Qt---- 点击按钮调用另一个窗口Ui

    -------------------------------------------------- #include "subdialog.h" SubDialog::SubDi ...

  7. VS 与 SQLite数据库 连接

    SQLite并没有一次性做到位,只有下载这些东西是不能放在vs2010中并马上使用的,下载下来的文件中有sqlite3.c/h/dll/def,还是不够用的.我们需要的sqlite3.lib文件并不在 ...

  8. centos中设置apache显示目录列表

    apache中显示目录列表 在http.conf中加入如下代码(如有虚拟主机配置,加在虚拟主机配置段内),并把主目录内的index.pho,index.html,index.htm文件删除 复制代码  ...

  9. 用sql语句生成 数据字典

    SELECT 表名=case when a.colorder=1 then d.name else '' end, 表说明=case when a.colorder=1 then isnull(f.v ...

  10. Chrome控制台输入多行js

    Chrome控制台输入多行js 分类: chrome2013-09-08 09:40 342人阅读 评论(0) 收藏 举报 控制台 Chrome控制台中回车默认是执行,要想输入换行,应按Enter+S ...