背景:代码里面有时候会把将要运行的内容放到主线程里面运行,但假设已经是主线程里面的代码调用dispatch_async的时候偶尔会出现crash,所以就须要推断是否已经在主线程里面了。

通常的做法类似于以下所代码:

    ......
if ([NSThread isMainThread]) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
......

所以在SDWebImage库里面进行了一次封装,把这部分内容放在了一个宏里面:

#define dispatch_main_async_safe(block)\
if ([NSThread isMainThread]) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}

这样就能够在代码里面调用dispatch_main_async_safe安全的分发任务到主线程里面执行



可是这个的问题是,宏里面的block是无法打断点调试的。比方:

dispatch_main_async_safe(^{
if(a) {
[self foo1];
}
else {
[self foo2];
}
});

我们无法在if推断那里加个断点,来step by step的进行调试。

所以,我才有了想要自己封装一个函数来调用的想法。

我们能够发现dispatch_async这类的方法事实上是C接口的,所以在封装的过程里面遇到非常多问题,搞不定。

最后经过网友的提醒,OC是能够直接调用C方法,而不须要把文件改为.mm后缀的,但假设调用C++方法,就须要把文件改为.mm后缀了。

我的代码里面有非常多.m文件,也有非常多.mm文件,于是我不得不封装C和C++的接口来使用。

下面是C接口:

头文件

//
// XXXDispatchMainQueueSafeC.h
//
// Created by robyzhou on 15/7/16.
// Copyright (c) 2015年 robyzhou. All rights reserved.
// #ifndef __XXX__XXXDispatchMainQueueSafeM__
#define __XXX__XXXDispatchMainQueueSafeM__ #include <stdio.h> typedef void(^Cblock)(); void dispatch_main_async_XXX_m(Cblock block); void dispatch_main_sync_XXX_m(Cblock block); #endif

m文件

//
// XXXDispatchMainQueueSafeC.c
// XXX
//
// Created by robyzhou on 15/7/16.
// Copyright (c) 2015年 robyzhou. All rights reserved.
// #include "XXXDispatchMainQueueSafeM.h" void dispatch_main_async_XXX_m(Cblock block) {
if ([NSThread isMainThread]) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
} void dispatch_main_sync_XXX_m(Cblock block) {
if ([NSThread isMainThread]) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
}

下面是C++接口:

头文件

//
// XXXDispatchMainQueueSafe.h
// XXX
//
// Created by robyzhou on 15/7/15.
// Copyright (c) 2015年 robyzhou. All rights reserved.
// #import <Foundation/Foundation.h> @interface XXXDispatchMainQueueSafe : NSObject typedef void(^block)(); void dispatch_main_async_XXX_mm(block block); void dispatch_main_sync_XXX_mm(block block); @end

mm文件

//
// XXXDispatchMainQueueSafe.m
// XXX
//
// Created by robyzhou on 15/7/15.
// Copyright (c) 2015年 robyzhou. All rights reserved.
// #import "XXXDispatchMainQueueSafeMM.h" @implementation XXXDispatchMainQueueSafe void dispatch_main_async_XXX_mm(block block) {
if ([NSThread isMainThread]) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
} void dispatch_main_sync_XXX_mm(block block) {
if ([NSThread isMainThread]) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
} @end

这样,假设你是在.m文件调用。就直接调用dispatch_main_async_XXX_m / dispatch_main_sync_XXX_m。假设你是在.mm文件调用。就直接调用dispatch_main_async_XXX_mm / dispatch_main_sync_XXX_mm。 比方:

dispatch_main_async_XXX_m(^{
if(a) {
[self foo1];
}
else {
[self foo2];
}
});

而且你能够在 block里面加断点进行调试



假设你有不论什么问题,欢迎留言。一起讨论,谢谢。

对dispatch_async到主线程的逻辑封装成C/C++接口类型的更多相关文章

  1. 对RedisTemplate接口二次封装成自定义工具接口

    开发过程中,经常使用redis数据库存储. 一般都是依赖注入redisTemplate,然后调用redisTemplate的api进行接口功能实现. 但是,如果对redisTemplate自带的API ...

  2. dispatch_async 子线程,主线程的简单用法

    子线程的使用方法: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{ //子线程的处理逻辑 ...

  3. Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解

    MainActivity如下: package cc.c; import android.app.Activity; import android.os.Bundle; import android. ...

  4. GCD多线程 在子线程中获取网络图片 在主线程更新

    子线程中得所有数据都可以直接拿到主线程中使用 //当触摸屏幕的时候,从网络上下载一张图片到控制器的view上显示 -(void)touchesBegan:(NSSet *)touches withEv ...

  5. 在Qt中将函数发送到主线程执行

    考虑这样一种需求,使用Qt的线程类QThread在后台执行操作(比如说拷贝文件)的时候发生了错误,产生了一个错误信息需要提醒给用户,在后台输出很显然是不够的,因为用户可能根据就没有任何控制台可供程序输 ...

  6. Java线程池主线程等待子线程执行完成

    今天讨论一个入门级的话题, 不然没东西更新对不起空间和域名~~ 工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一 ...

  7. WebWorker 中将已处理好的 VDOM 数据提交主线程渲染 DOM

    上篇文章讲了 WebWorker 的简单用法,其实网上很多类似的文章,我写的也比较垃圾.不会的建议可以网上看比较好点的资料. 这里我会先讲下我的大致思路.然后会贴上一堆不实用的垃圾代码供参考. Web ...

  8. iOS开发之GCD同步主线程、异步主线程

    /** 在主线程执行block */ + (void)gs_synExecuteOnMainThread:(void (^)(void))block { if ((nil == block) || ( ...

  9. Task的在主线程处理异常信息的Helper类

    最近使用task时候需要把异常记录日志,直接注入非单例模式的实例进入异步线程,在高并发情况下会出现一些问题. 所以需要把异常反馈给主线程 ,并且不在主线程里进行等待,研究相关资料后,自己写了一个简单的 ...

随机推荐

  1. 命令终端执行python

    windows进入cmd 1.进入cmd窗口,找到存放py文件的地址(如E:\learn_mock) 2.退出python,输入exit() linux下一样

  2. 模板引擎freemarker的使用(二)

    freemarker默认配置使用时,如果传到前端的值为null或者不存在,后台会报错. 处理方法: <bean id="freemarkerConfig" class=&qu ...

  3. QT_8_Qt中的事件处理_定时器事件_定时器类_事件分发器_事件过滤器_绘图事件_高级绘图事件_绘图设备_QFile 文件读写_QFileInfo文件信息

    Qt中的事件处理 1.1. 捕获QLabel中是鼠标事件 1.2. enterevent 鼠标进入 1.3. leaveevent 鼠标离开 1.4. 鼠标按下MyLabel::mousePressE ...

  4. 开源代码生成器,基于mybatis-generator扩展,结合freemarker

    git源码地址:https://github.com/JonSnow592622272/free-generator-code 码云gitee源码地址:https://gitee.com/a59262 ...

  5. Java中的反射--Reflect

    在张孝祥老师的Java讲解中,学习到了Java反射的一部分知识,觉得有必要好好学习一下哈. 一.反射的理解 经典总结:反射就是把Java类中的各种成分映射成为相应的Java类 例如:一个Java类中用 ...

  6. java值的传递

    public class Example { String str = new String("good"); char[] ch = {'a','b','c'}; public ...

  7. 基于HLS(HTTP Live Streaming)的视频直播分析与实现

    转自:http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html HLS(HTTP Live Streaming)的分析: HTT ...

  8. mysql alter修改数据库表结构用法

    1.alter操作表字段 (1)增加字段 alter table 表名 add 字段名 字段类型: alter table student add name varchar(10): (2)修改字段 ...

  9. 【thinkPHP5实现文件上传】

    上传文件 ThinkPHP5.0对文件上传的支持更加简单. 内置的上传只是上传到本地服务器,上传到远程或者第三方平台的话需要自己扩展. 假设表单代码如下: <form action=" ...

  10. Week06-继承、多态、抽象类与接口

    Week06-继承.多态.抽象类与接口 1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 关键字:接口,Comparable,interface关键字,Comparator,继承 ...