背景:代码里面有时候会把将要运行的内容放到主线程里面运行,但假设已经是主线程里面的代码调用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. docker 的容器入门

    Linux Namespace LXC所实现的隔离性主要是来自kernel的namespace, 其中pid, net, ipc, mnt, uts 等namespace将container的进程, ...

  2. ADB相关指令实例详解

    1.获取物理设备相关信息: adb devices 2.apk安装 2.1 新的应用(该应用未安装) adb -s 设备序列号 install apk路径 2.2 应用已安装,重安装覆盖 adb -s ...

  3. 在实现栈中原来功能的基础上,获得一个栈中最小值,要求时间复杂度 bigO(1)

    思路: 准备两个栈 stackData stackMin package my_basic; import java.util.Stack; public class GetMinStack { St ...

  4. 项目中常用的js方法(持续更新)

    <script> var utils = { //时间戳转日期(timestamp:时间戳 默认当前时间) dateFormat: function(timestamp = new Dat ...

  5. debian swoole环境

    debian 9.8 #目录 /lnmp/soure #软件下载位置 /lnmp/data #测试程序位置 安装php-7.3.3 #卸载apt安装的 apt-get autoremove php7* ...

  6. tornado框架基础06-SQLAlchemy连接数据库

    01 ORM 在服务器后台,数据是要存储在数据库的,但是如果项目在开发和部署的时候,是使用的不同的数据库,该怎么办呢?是不是需要把所有的 SQL 语句都再重新写一遍呢? 和数据库相关,不同的数据库需要 ...

  7. 解决safari里面淘宝京东页面无法打开以及打开后乱码的问题!

    sqlite3 ~/Library/Keychains/*/ocspcache.sqlite3 'DELETE FROM responses WHERE responderURI LIKE " ...

  8. sql语句中嵌套2层循环

    declare @year intdeclare @month intset @year=2008 while(@year<=2011)beginset @month=1while(@month ...

  9. C#窗体学生成绩管理系统

    c#学生成绩管理系统 实现用户登录.注册 所有成绩查询.个人成绩查询 管理员审核.添加.删除用户 项目源码GIT:https://github.com/soulsjie/StuScoreMa.git

  10. [HDU5919]Sequence II

    [HDU5919]Sequence II 试题描述 Mr. Frog has an integer sequence of length n, which can be denoted as a1,a ...