返回顶部
首页 > 资讯 > 精选 >iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用
  • 432
分享到

iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用

2023-07-05 19:07:50 432人浏览 安东尼
摘要

这篇文章主要介绍“iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用”,在日常操作中,相信很多人在ioS GCD之dispatch_group_enter和disp

这篇文章主要介绍“iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用”,在日常操作中,相信很多人在ioS GCD之dispatch_group_enter和dispatch_group_leave怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

如何使用

通过一个例子来看下如何使用 dispatch_group_enterdispatch_group_leave

{    // 首先 需要创建一个线程组    dispatch_group_t group = dispatch_group_create();    // 任务1    dispatch_group_enter(group);    NSURLSessionDataTask *task1 = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@""] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        NSLog(@"任务1完成");        dispatch_group_leave(group);    }];    [task1 resume];     // 任务2    dispatch_group_enter(group);    NSURLSessionDataTask *task2 = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@""] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {        NSLog(@"任务2完成");        dispatch_group_leave(group);    }];    [task2 resume];    // 全部完成    dispatch_group_notify(group, dispatch_get_main_queue(), ^(){        NSLog(@"全部完成");    });}

任务1和任务2执行完成之后,才会执行全部完成中的任务。

**注意:**在使用时,dispatch_group_enter 和 dispatch_group_leave 需要成对出现,如果 dispatch_group_leave 的调用次数多于 dispatch_group_enter 的调用次数,程序会 crash。相反,虽然不会发生 crash , 但可能不会达到预期效果。

crash 场景分析

使用场景是,需要异步获取多个图片封面,所有都获取完成后,在执行指定任务,代码示例如下:

- (void)fetchCovers {    dispatch_queue_t queue = dispatch_queue_create("com.demo.xxx", DISPATCH_QUEUE_CONCURRENT);    dispatch_group_t group = dispatch_group_create();    for (int i = 0; i < 40; ++i) {        dispatch_group_enter(group);        dispatch_async(queue, ^{            [self fetchCoverByPHAsset:asset targetSize:CGSizeMake(200, 200) resultHandler:^(UIImage * _Nonnull, NSDictionary * _Nonnull, BOOL) {            dispatch_group_leave(group);        }];        });    }    dispatch_group_notify(group, dispatch_get_main_queue(), ^(){        // 全部完成后 执行指定任务    });}- (void)fetchCover:(PHAsset *)asset targetSize:(CGSize)targeSize resultHandler:(void (^)(UIImage * _Nonnull, NSDictionary * _Nonnull, BOOL))resultHandler {    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];    if (@available(iOS 14.0, *)) {        options.version = PHImageRequestOptionsVersionCurrent;    }    options.networkAccessAllowed = YES;    [[PHImageManager defaultManager] requestImageForAsset:asset                                               targetSize:targeSize                                              contentMode:PHImageContentModeAspectFill                                                  options:options                                            resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {        if (resultHandler) {            resultHandler(result, info, [[info objectForKey:PHImageResultIsDegradedKey] boolValue]);        }    }];}

这里有个小 tips : 在使用 requestImageForAsset 获取图片时,如果 options 的 deliveryMode 属性使用默认值,在异步获取图片时,其回调可能会走2次。解决方案是将其显示设置为 PHImageRequestOptionsDeliveryModeHighQualityFORMat 或 PHImageRequestOptionsDeliveryModeFastFormat。

    options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat; // 或 PHImageRequestOptionsDeliveryModeHighQualityFormat

因为获取图片封面的回调可能会走 2 次,从而导致 dispatch_group_leave 调用次数多于 dispatch_group_enter 的调用次数,因此可能会发生 crash。

源码实现

  • dispatch_group_enter

void dispatch_group_enter(dispatch_group_t dg){    uint32_t old_bits = os_atomic_sub_orig2o(dg, dg_bits,    DISPATCH_GROUP_VALUE_INTERVAL, acquire);    uint32_t old_value = old_bits & DISPATCH_GROUP_VALUE_MASK;    if (unlikely(old_value == 0)) {    _dispatch_retain(dg); // <rdar://problem/22318411>    }    if (unlikely(old_value == DISPATCH_GROUP_VALUE_MAX)) {    DISPATCH_CLIENT_CRASH(old_bits,    "Too many nested calls to dispatch_group_enter()");    }}
  • dispatch_group_leave

void dispatch_group_leave(dispatch_group_t dg){       uint64_t new_state, old_state = os_atomic_add_orig2o(dg, dg_state,    DISPATCH_GROUP_VALUE_INTERVAL, release);    uint32_t old_value = (uint32_t)(old_state &amp; DISPATCH_GROUP_VALUE_MASK);    if (unlikely(old_value == DISPATCH_GROUP_VALUE_1)) {    old_state += DISPATCH_GROUP_VALUE_INTERVAL;    do {    new_state = old_state;    if ((old_state &amp; DISPATCH_GROUP_VALUE_MASK) == 0) {    new_state &amp;= ~DISPATCH_GROUP_HAS_WAITERS;    new_state &amp;= ~DISPATCH_GROUP_HAS_NOTIFS;    } else {    new_state &amp;= ~DISPATCH_GROUP_HAS_NOTIFS;    }    if (old_state == new_state) break;    } while (unlikely(!os_atomic_cmpxchgv2o(dg, dg_state,    old_state, new_state, &amp;old_state, relaxed)));    return _dispatch_group_wake(dg, old_state, true);    }    if (unlikely(old_value == 0)) {    DISPATCH_CLIENT_CRASH((uintptr_t)old_value,    "Unbalanced call to dispatch_group_leave()");    }}

到此,关于“iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用

本文链接: https://lsjlt.com/news/354685.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用
    这篇文章主要介绍“iOS GCD之dispatch_group_enter和dispatch_group_leave怎么使用”,在日常操作中,相信很多人在iOS GCD之dispatch_group_enter和disp...
    99+
    2023-07-05
  • iOS定时器选择及CADisplayLink NSTimer和GCD使用的方法是什么
    本篇内容介绍了“iOS定时器选择及CADisplayLink NSTimer和GCD使用的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读...
    99+
    2023-07-05
  • IOS NSTimeInterval怎么使用
    在iOS中,NSTimeInterval是一种时间间隔的数据类型,以秒为单位。你可以使用NSTimeInterval来表示两个时间点...
    99+
    2024-03-05
    IOS
  • iOS砸壳系列之三:Frida介绍和使用
    当涉及从App Store下载应用程序时,它们都是已安装的iOS应用(IPA)存储在设备上。这些应用程序通常带有保护的代码和资源,以限制用户对其进行修改或者逆向工程。 然而,有时候,为了进行调试、制作...
    99+
    2023-10-09
    ios cocoa macos iOS逆向 objective-c
  • iOS中NavigationController怎么使用
    在iOS中,可以通过以下步骤来使用NavigationController:1. 创建一个NavigationController对...
    99+
    2023-09-26
    iOS
  • iOS中CocoaPods怎么使用
    要在iOS中使用CocoaPods,您需要按照以下步骤进行操作:1. 首先,您需要在您的mac上安装CocoaPods。打开终端并输...
    99+
    2023-09-29
    iOS
  • iOS中CAKeyframeAnimation怎么使用
    在iOS中,可以使用CAKeyframeAnimation实现关键帧动画。下面是使用CAKeyframeAnimation的步骤:1...
    99+
    2023-09-29
    iOS
  • iOS中PerformSelector怎么使用
    在iOS中,`performSelector`方法用于调用对象的指定方法。使用方法如下:1. 调用无参数方法:```swiftlet...
    99+
    2023-09-06
    iOS
  • iOS中AFNetworking怎么使用
    在iOS中使用AFNetworking可以按照以下步骤进行:1. 导入AFNetworking库:将AFNetworking库添加到...
    99+
    2023-09-21
    iOS
  • IBeacon怎么在IOS中使用
    这期内容当中小编将会给大家带来有关IBeacon怎么在IOS中使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。什么是iBeacon?iBeacon 是苹果公司2013年9月发布的移动设备用OS(iOS7...
    99+
    2023-06-14
  • iOS开发中AvaudioPlayer怎么使用
    在iOS开发中,你可以使用AVAudioPlayer类来播放音频文件。下面是使用AVAudioPlayer的基本步骤:1. 导入AV...
    99+
    2023-09-13
    iOS
  • iOS开发中rangeOfString怎么使用
    rangeOfString是一个NSString类的方法,用于在字符串中查找指定的子字符串。它返回一个NSRange结构体,指示子字...
    99+
    2023-09-15
    iOS
  • iOS开发中nstimeinterval怎么使用
    NSTimeInterval是一个双精度浮点型的时间间隔,它表示自2001年1月1日午夜(GMT)以来的秒数。在iOS开发中,我们可...
    99+
    2023-08-24
    nstimeinterval
  • 怎么在IOS中使用Cordova插件
    这篇文章给大家分享的是有关怎么在IOS中使用Cordova插件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、准备插件功能:打开IOS相机1:创建插件plugman create --name [插件名称] -...
    99+
    2023-06-14
  • 怎么在IOS上使用ReplayKit与RTC
    小编给大家分享一下怎么在IOS上使用ReplayKit与RTC,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!直播场景下的屏幕分享,不仅要将当前显示器所展示的画面分...
    99+
    2023-06-14
  • 怎么使用IOS实现WIFI传输
    这篇文章主要介绍了怎么使用IOS实现WIFI传输,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。问题业务场景上存在需要将手机里的文件、图片传递给其他的设备,不仅仅局限于传书、资...
    99+
    2023-06-14
  • iOS开发CGContextRef画图怎么使用
    这篇“iOS开发CGContextRef画图怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“iOS开发CGContex...
    99+
    2023-06-30
  • python之class类和方法怎么使用
    本篇内容主要讲解“python之class类和方法怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python之class类和方法怎么使用”吧!类和方法的概念和实例类(Class):用来描...
    99+
    2023-07-05
  • 怎么在IOS中使用ADisplayLink刷新屏幕
    怎么在IOS中使用ADisplayLink刷新屏幕?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。什么是CADisplayLink我们在应用中创建一个新的CADisplayL...
    99+
    2023-06-15
  • Linux之curses.h文件怎么安装和使用
    要安装和使用curses.h文件,您需要按照以下步骤进行操作:1. 安装ncurses库:在Linux系统中,curses.h是nc...
    99+
    2023-09-14
    Linux
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作