背景:代码里面有时候会把将要运行的内容放到主线程里面运行,但假设已经是主线程里面的代码调用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. params.row[params.column.key] vue h函数 当前单元格 h函数 div 属性 值或数组 render

    params.row[params.column.key] vue h函数 当前单元格 h函数 div 属性 值或数组 render

  2. Java文件编译与反编译:javac命令和javap命令

    1.创建一个Test.java文件,并输入内容 public class Test{ private int m; public int inc(){ return m + 1; } } 2.使用ja ...

  3. js数字转金额,ajax调用接口,后台返回html(完整页面),打开新窗口并写入html

    一.转换成金额形式 function toMoney(num){ if(num){ if(isNaN(num)) { alert("金额中含有不能识别的字符"); return; ...

  4. xcode菜单栏

    File  文件 Edit  编辑 View 视图 Navigate 导航 Editor 编辑 Product 产品 Window  窗口 Help 帮助 File  文件 New 新建        ...

  5. noip2019——动态规划刷题历程

    加粗的是值得总结的 从洛谷的普及题开始刷题: 背包式dp(有些技巧的) 1.p2639[USACO09OCT]Bessie的体重问题 -p1049取模意义下01背包 技巧:重量=价值 2.金明的预算问 ...

  6. DNS域名系统

    1. 什么是DNS? DNS是域名系统的缩写,DNS通过将域名与实际的Web服务器连接来帮助引导Internet上的流量.从本质上讲,它需要一个人性化的请求 – 像simcf.cc这样的域名 – 并将 ...

  7. 网络设置命令--ifconfig.setup

    ifconfig命令 作用:用于显示以及设置当前活动网卡信息 一.  显示当前活动网卡信息 ifconfig 从上面可以看到当前主要有2块活动网卡,eth0:代表当前本地真实网卡 lo:代表回访网卡, ...

  8. docker-compose文件语法解析(v3.x)

    文件配置 compose文件是一个定义服务(service).网络(network)和卷(volume)的YAML文件 .Compose 文件的默认路径是 ./docker-compose.yml 提 ...

  9. tomcat 403错误和ls: cannot open directory '.': Permission denied

    在centos7 linux系统上使用docker进行tomcat部署项目测试的时候发现第一个错误:浏览器返回403 错误,显然是一个权限问题,禁止访问.下面是我一步一步的操作: 1 使用的docke ...

  10. Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)

    题意: 你有一个体积为N的箱子和两种数量无限的宝物.宝物1的体积为S1,价值为V1:宝物2的体积为S2,价值为V2.输入均为32位带符号的整数.你的任务是最多能装多少价值的宝物? 分析: 分类枚举, ...