zoukankan      html  css  js  c++  java
  • IOS-线程(GCD)

    一、GCD的使用

    //
    //  IBController3.m
    //  IBCoder1
    //
    //  Created by Bowen on 2018/4/25.
    //  Copyright © 2018年 BowenCoder. All rights reserved.
    //
    
    #import "IBController3.h"
    
    @interface IBController3 ()
    
    @end
    
    /*
     进程:执行中的应用程序【一个应用程序可以有很多进程(网游双开),在iOS中一个app只有一个进程。】
     资源分配最小单元
     线程:进程中的一个执行序列,执行调度的最小单元
     
     线程与进程的区别:
     a.地址空间和其它资源:进程间拥有独立内存,进程是资源分配的基本单位;线程隶属于某一进程,且同一进程的各线程间共享内存(资源),线程是cpu调度的基本单位。
     b.通信:进程间相互独立,通信困难,常用的方法有:管道,信号,套接字,共享内存,消息队列等;线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
     c.调度和切换:线程上下文切换比进程上下文切换要快。进程间切换要保存上下文,加载另一个进程;而线程则共享了进程的上下文环境,切换更快。
     
     一、简介
     1.什么是GCD
     全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
     纯C语言,提供了非常多强大的函数
     
     2.GCD的优势
     GCD是苹果公司为多核的并行运算提出的解决方案
     GCD会自动利用更多的CPU内核(比如双核、四核)
     GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
     程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
     
     二、任务和队列
     1.GCD中有2个核心概念
     任务:执行什么操作
     队列:用来存放任务
     
     2.GCD的使用就2个步骤
     定制任务
     确定想做的事情
     
     3.将任务添加到队列中
     GCD会自动将队列中的任务取出,放到对应的线程中执行
     任务的取出遵循队列的FIFO原则:先进先出,后进后出
     
     三、执行任务
     1.GCD中有2个用来执行任务的函数
     用同步的方式执行任务
     dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
     queue:队列
     block:任务
     
     2.用异步的方式执行任务
     dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
     
     3.同步和异步的区别
     同步:只能在当前线程中执行任务,不具备开启新线程的能力
     异步:可以在新的线程中执行任务,具备开启新线程的能力
     
     四、队列的类型
     1.GCD的队列可以分为2大类型
     并发队列(Concurrent Dispatch Queue)
     可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
     并发功能只有在异步(dispatch_async)函数下才有效
     
     2.串行队列(Serial Dispatch Queue)
     让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
     
     五、容易混淆的术语
     1.有4个术语比较容易混淆:同步、异步、并发、串行
     同步和异步主要影响:能不能开启新的线程
     同步:在当前线程中执行任务,不具备开启新线程的能力
     异步:在新的线程中执行任务,具备开启新线程的能力
     
     2.并发和串行主要影响:任务的执行方式
     并发:多个任务并发(同时)执行
     串行:一个任务执行完毕后,再执行下一个任务
     
     六、并发队列
     1.GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
     使用dispatch_get_global_queue函数获得全局的并发队列
     dispatch_queue_t dispatch_get_global_queue(
     dispatch_queue_priority_t priority, // 队列的优先级
     unsigned long flags); // 此参数暂时无用,用0即可
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 获得全局并发队列
     
     2.全局并发队列的优先级
     #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
     #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
     #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
     #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
     
     七、串行队列
     1.GCD中获得串行有2种途径
     使用dispatch_queue_create函数创建串行队列
     dispatch_queue_t
     dispatch_queue_create(const char *label, // 队列名称
     dispatch_queue_attr_t attr); // 队列属性,一般用NULL即可
     dispatch_queue_t queue = dispatch_queue_create("cn.itcast.queue", NULL); // 创建
     dispatch_release(queue); // 非ARC需要释放手动创建的队列
     
     2.使用主队列(跟主线程相关联的队列)
     主队列是GCD自带的一种特殊的串行队列
     放在主队列中的任务,都会放到主线程中执行
     使用dispatch_get_main_queue()获得主队列
     dispatch_queue_t queue = dispatch_get_main_queue();
     
     八、各种队列的执行效果
     注意
     使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列
     
     九、线程间通信示例
     1.从子线程回到主线程
     dispatch_async(
     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     // 执行耗时的异步操作...
     dispatch_async(dispatch_get_main_queue(), ^{
     // 回到主线程,执行UI刷新操作
     });
     });
     
     十、延时执行
     iOS常见的延时执行有2种方式
     调用NSObject的方法
     [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
     // 2秒后再调用self的run方法
     
     使用GCD函数
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
     // 2秒后执行这里的代码... 在哪个线程执行,跟队列类型有关
     
     });
     
     十一、一次性代码
     使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     // 只执行1次的代码(这里面默认是线程安全的)
     });
     
     十二、队列组
     1.有这么1种需求
     首先:分别异步执行2个耗时的操作
     其次:等2个异步操作都执行完毕后,再回到主线程执行操作
     
     2.如果想要快速高效地实现上述需求,可以考虑用队列组
     dispatch_group_t group =  dispatch_group_create();
     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     // 执行1个耗时的异步操作
     });
     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     // 执行1个耗时的异步操作
     });
     dispatch_group_notify(group, dispatch_get_main_queue(), ^{
     // 等前面的异步操作都执行完毕后,回到主线程...
     });
     
     十三、Core Foundation
     Foundation : OC
     Core Foundation : C
     Foundation和Core Foundation可以相互转化
     
     NSString *str = @"123";
     CFStringRef str2 = (__bridge CFStringRef)str;
     NSString *str3 = (__bridge NSString *)(str2);
     
     CFArrayRef --- NSArray
     CFDictionaryRef --- NSDirectory
     CFNumberRef --- NSNumber
     
     凡是函数名中带有createcopy
    etain
    ew等字眼,都应该再不需要的时候进行release
     GCD的数据类型在ARC环境下不需要release
     CF(Core Foundation)的数据类型在ARC环境下还需要release
     
     Core Foundation中手动创建的数据类型,需要手动释放
     CFArrayRef array = CFArrayCreate(NULL, NULL, 10, NULL);
     CFRelease(array);
     
     CGPathRef path = CGPathCreateMutable();
     CGPathRelease(path);
     
     
     注意千万分清:主线程和主队列概念
    
     
     */
    
    @implementation IBController3
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor whiteColor];
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        NSLog(@"-------------------------------------");
    
    //    [self test1];
    //    [self test2];
    //    [self test3];
    //    [self test4];
    //    [self test5];
    //    [self test6];
        [self test7];
    //    [self test8];
    //    [self test9];
        NSLog(@"++++++++++++++++++++++++++++++++++++");
        
    }
    
    /**
     同步主队列
     在主线程中执行
     理解:主队列在同步任务的条件下,必须主线程空闲的时候,才可以添加任务到队列中
     */
    - (void)test9 {
        dispatch_queue_t queue = dispatch_get_main_queue();
        dispatch_sync(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
    }
    
    /**
     * sync(同步) --串行队列
     * 会不会创建线程:不会
     * 线程的执行方法:串行(一个任务执行完毕后,再执行下一个任务)
     * 在主线程中执行串行队列,完成后回到主线程在执行主队列
     */
    - (void)test8 {
        dispatch_queue_t queue = dispatch_queue_create("bowen", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
    }
    
    /**
     * sync(同步) --并发队列
     * 会不会创建线程:不会,在主线程中运行
     * 任务的执行方式:串行(一个任务执行完毕后,再执行下一个任务)
     * 并发队列失去并发功能
     * 在主线程中执行并发队列,完成后回到主线程执行主队列
     */
    - (void)test7 {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_sync(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
    
    }
    
    /**
     * async(异步) --主队列(很常用)(特殊)
     * 会不会创建线程:不会
     * 任务的执行方式:串行
     * 一般用在线程之间的通讯
     * 理解:异步主队列,先把任务添加到主队列中,等主线程空闲执行任务
     */
    - (void)test6 {
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        dispatch_async(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
    }
    
    /**
     * async(异步) --串行队列(有时用)
     * 会不会创建线程:会,创建一条
     * 线程的执行方法:串行(一个任务执行完毕后,再执行下一个任务)
     */
    - (void)test5 {
        dispatch_queue_t queue = dispatch_queue_create("bowen", DISPATCH_QUEUE_SERIAL);
        
        dispatch_async(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
    
    }
    
    
    
    /**
     * async(异步) --并发队列(最常用)
     * 会不会创建线程:会,并且创建多条线程
     * 任务的执行方式:并发执行
     */
    - (void)test4 {
        
        dispatch_queue_t queue = dispatch_queue_create("bowen", DISPATCH_QUEUE_CONCURRENT);
        
        dispatch_async(queue, ^{
            NSLog(@"----1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----2----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----3----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----4----%@",[NSThread currentThread]);
        });
        
    }
    
    /**
     组内并行,组间串行
     */
    - (void)test1 {
        
        dispatch_group_t group1 = dispatch_group_create();
        dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 1---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 2---%@",[NSThread currentThread]);
    
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 3---%@",[NSThread currentThread]);
    
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 4---%@",[NSThread currentThread]);
    
        });
        
        dispatch_group_wait(group1,DISPATCH_TIME_FOREVER);
        
        dispatch_group_t group2 = dispatch_group_create();
        dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 1---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 2---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 3---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 4---%@",[NSThread currentThread]);
        });
    }
    
    
    - (void)test2 {
        NSOperationQueue *oq = [[NSOperationQueue alloc] init];
        oq.maxConcurrentOperationCount = 1;
        [oq addOperationWithBlock:^{
            NSLog(@"1--%@",[NSThread currentThread]);
        }];
        [oq addOperationWithBlock:^{
            NSLog(@"2--%@",[NSThread currentThread]);
        }];
        [oq addOperationWithBlock:^{
            NSLog(@"3--%@",[NSThread currentThread]);
        }];
        [oq addOperationWithBlock:^{
            NSLog(@"4--%@",[NSThread currentThread]);
        }];
    }
    
    /**
     组内串行,组间并行
     */
    - (void)test3 {
        
        dispatch_group_t group1 = dispatch_group_create();
        dispatch_queue_t queue1 = dispatch_queue_create("leador", DISPATCH_QUEUE_SERIAL);
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 1---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 2---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 3---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group1, queue1, ^{
            NSLog(@"group1 --- 4---%@",[NSThread currentThread]);
        });
        
        
        dispatch_group_t group2 = dispatch_group_create();
        dispatch_queue_t queue2 = dispatch_queue_create("leador1", DISPATCH_QUEUE_SERIAL);
    
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 1---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 2---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 3---%@",[NSThread currentThread]);
        });
        dispatch_group_async(group2, queue2, ^{
            NSLog(@"group2 --- 4---%@",[NSThread currentThread]);
        });
    }
    
    
    @end

    二、GCD线程之间通信

     1 //
     2 //  ViewController.m
     3 //  IOS_0117_GCD通信
     4 //
     5 //  Created by ma c on 16/1/17.
     6 //  Copyright (c) 2016年 博文科技. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 
    13 @property (nonatomic, strong) UIButton *btn;
    14 
    15 @end
    16 
    17 @implementation ViewController
    18 
    19 - (void)viewDidLoad {
    20     [super viewDidLoad];
    21     
    22     self.btn = [UIButton buttonWithType:UIButtonTypeCustom];
    23     [self.btn setFrame:CGRectMake(100, 150, 150, 150)];
    24     [self.btn setBackgroundColor:[UIColor purpleColor]];
    25     [self.view addSubview:self.btn];
    26 }
    27 
    28 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    29 {
    30     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    31     dispatch_async(queue, ^{
    32         
    33         NSLog(@"download-----%@",[NSThread currentThread]);
    34         //子线程下载图片
    35         NSURL *url = [NSURL URLWithString:@"http://www.qiyue.com/uploadfile/2016/0103/20160103105808532.jpg"];
    36         NSData *data = [NSData dataWithContentsOfURL:url];
    37         UIImage *image = [UIImage imageWithData:data];
    38         
    39         //回到主线程
    40         dispatch_queue_t mainQueue = dispatch_get_main_queue();
    41         dispatch_async(mainQueue, ^{
    42             
    43             NSLog(@"刷新---------%@---%@",[NSThread currentThread],image);
    44             [self.btn setBackgroundImage:image forState:UIControlStateNormal];
    45             
    46         });
    47     });
    48 }
    49 
    50 @end

     三、延迟执行

     1 //
     2 //  ViewController.m
     3 //  IOS_0117_GCD线程通信
     4 //
     5 //  Created by ma c on 16/1/17.
     6 //  Copyright (c) 2016年 博文科技. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 
    13 @end
    14 
    15 @implementation ViewController
    16 
    17 - (void)viewDidLoad {
    18     [super viewDidLoad];
    19     // Do any additional setup after loading the view, typically from a nib.
    20 }
    21 
    22 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    23 {
    24 //    [self delay1];
    25 //    [self delay2];
    26     
    27 
    28 }
    29 
    30 - (void)delay3
    31 {
    32     NSLog(@"-----touchesBegan1------");
    33     //3s后回到主线程执行block代码
    34     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    35         NSLog(@"-----task------%@",[NSThread currentThread]);
    36     });
    37     
    38     //3s后自动开启新线程执行block代码
    39     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    40     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
    41         NSLog(@"-----task------%@",[NSThread currentThread]);
    42     });
    43     
    44     NSLog(@"-----touchesBegan2------");
    45 }
    46 
    47 - (void)delay2
    48 {
    49     NSLog(@"-----touchesBegan1------");
    50     
    51     //定制好延迟任务后,不会卡主当前线程
    52     [self performSelector:@selector(run) withObject:@"http://" afterDelay:3];
    53     
    54     NSLog(@"-----touchesBegan2------");
    55 }
    56 
    57 - (void)run:(NSString *)url
    58 {
    59     NSLog(@"run------%@---%@",[NSThread currentThread], url);
    60 }
    61 
    62 - (void)delay1
    63 {
    64     NSLog(@"------begin------");
    65     
    66     //延迟线程不要用sleep,坏处:卡主线程
    67     [NSThread sleepForTimeInterval:3];
    68     NSLog(@"下载图片");
    69 }
    70 @end

    四、GCD一次性代码

     1 //
     2 //  ViewController.m
     3 //  IOS_0117_GCD一次性代码
     4 //
     5 //  Created by ma c on 16/1/17.
     6 //  Copyright (c) 2016年 博文科技. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 
    11 @interface ViewController ()
    12 
    13 @property (nonatomic, assign) BOOL hasExecuted;
    14 
    15 @end
    16 
    17 @implementation ViewController
    18 
    19 - (void)viewDidLoad {
    20     [super viewDidLoad];
    21     // Do any additional setup after loading the view, typically from a nib.
    22 }
    23 
    24 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    25 {
    26 //    [self fun1];
    27     [self fun2];
    28 }
    29 
    30 - (void)fun2
    31 {
    32     static dispatch_once_t onceToken;
    33     dispatch_once(&onceToken, ^{
    34         
    35         NSLog(@"下载图片");
    36     });
    37 }
    38 - (void)fun1
    39 {
    40     if (self.hasExecuted) return;
    41     
    42     NSLog(@"下载图片");
    43     self.hasExecuted = YES;
    44 }
    45 
    46 @end

    五、队列组

      1 //
      2 //  HMViewController.m
      3 //  03-队列组(了解)
      4 //
      5 //  Created by apple on 14-9-16.
      6 //  Copyright (c) 2014年 heima. All rights reserved.
      7 //
      8 
      9 #import "HMViewController.h"
     10 
     11 // 1.分别下载2张图片:大图片、LOGO
     12 // 2.合并2张图片
     13 // 3.显示到一个imageView身上
     14 
     15 @interface HMViewController ()
     16 @property (weak, nonatomic) IBOutlet UIImageView *imageView;
     17 @property (nonatomic, strong) UIImage *image1;
     18 @property (nonatomic, strong) UIImage *image2;
     19 @end
     20 
     21 @implementation HMViewController
     22 
     23 - (void)viewDidLoad
     24 {
     25     [super viewDidLoad];
     26     
     27 }
     28 
     29 // 2D绘图  Quartz2D
     30 // 合并图片 -- 水印
     31 
     32 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
     33 {
     34     // 1.队列组
     35     dispatch_group_t group = dispatch_group_create();
     36     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     37     
     38     // 2.下载图片1
     39     __block UIImage *image1 = nil;
     40     dispatch_group_async(group, queue, ^{
     41         NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
     42         NSData *data1 = [NSData dataWithContentsOfURL:url1];
     43         image1 = [UIImage imageWithData:data1];
     44     });
     45     
     46     // 3.下载图片2
     47     __block UIImage *image2 = nil;
     48     dispatch_group_async(group, queue, ^{
     49         NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
     50         NSData *data2 = [NSData dataWithContentsOfURL:url2];
     51         image2 = [UIImage imageWithData:data2];
     52     });
     53     
     54     // 4.合并图片 (保证执行完组里面的所有任务之后,再执行notify函数里面的block)
     55     dispatch_group_notify(group, queue, ^{
     56         // 开启一个位图上下文
     57         UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
     58         
     59         // 绘制第1张图片
     60         CGFloat image1W = image1.size.width;
     61         CGFloat image1H = image1.size.height;
     62         [image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
     63         
     64         // 绘制第2张图片
     65         CGFloat image2W = image2.size.width * 0.5;
     66         CGFloat image2H = image2.size.height * 0.5;
     67         CGFloat image2Y = image1H - image2H;
     68         [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
     69         
     70         // 得到上下文中的图片
     71         UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
     72         
     73         // 结束上下文
     74         UIGraphicsEndImageContext();
     75         
     76         // 5.回到主线程显示图片
     77         dispatch_async(dispatch_get_main_queue(), ^{
     78             self.imageView.image = fullImage;
     79         });
     80     });
     81 }
     82 
     83 - (void)test2
     84 {
     85     // 异步下载
     86     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     87         // 1.下载第1张
     88         NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
     89         NSData *data1 = [NSData dataWithContentsOfURL:url1];
     90         self.image1 = [UIImage imageWithData:data1];
     91         
     92         [self bindImages];
     93     });
     94     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     95         // 2.下载第2张
     96         NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
     97         NSData *data2 = [NSData dataWithContentsOfURL:url2];
     98         self.image2 = [UIImage imageWithData:data2];
     99         
    100         [self bindImages];
    101     });
    102 }
    103 
    104 - (void)bindImages
    105 {
    106     if (self.image1 == nil || self.image2 == nil) return;
    107     
    108     // 3.合并图片
    109     // 开启一个位图上下文
    110     UIGraphicsBeginImageContextWithOptions(self.image1.size, NO, 0.0);
    111     
    112     // 绘制第1张图片
    113     CGFloat image1W = self.image1.size.width;
    114     CGFloat image1H = self.image1.size.height;
    115     [self.image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
    116     
    117     // 绘制第2张图片
    118     CGFloat image2W = self.image2.size.width * 0.5;
    119     CGFloat image2H = self.image2.size.height * 0.5;
    120     CGFloat image2Y = image1H - image2H;
    121     [self.image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
    122     
    123     // 得到上下文中的图片
    124     UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
    125     
    126     // 结束上下文
    127     UIGraphicsEndImageContext();
    128     
    129     // 4.回到主线程显示图片
    130     dispatch_async(dispatch_get_main_queue(), ^{
    131         self.imageView.image = fullImage;
    132     });
    133 }
    134 
    135 - (void)test1
    136 {
    137     // 异步下载
    138     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    139         // 1.下载第1张
    140         NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
    141         NSData *data1 = [NSData dataWithContentsOfURL:url1];
    142         UIImage *image1 = [UIImage imageWithData:data1];
    143         
    144         // 2.下载第2张
    145         NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
    146         NSData *data2 = [NSData dataWithContentsOfURL:url2];
    147         UIImage *image2 = [UIImage imageWithData:data2];
    148         
    149         // 3.合并图片
    150         // 开启一个位图上下文
    151         UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
    152         
    153         // 绘制第1张图片
    154         CGFloat image1W = image1.size.width;
    155         CGFloat image1H = image1.size.height;
    156         [image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
    157         
    158         // 绘制第2张图片
    159         CGFloat image2W = image2.size.width * 0.5;
    160         CGFloat image2H = image2.size.height * 0.5;
    161         CGFloat image2Y = image1H - image2H;
    162         [image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
    163         
    164         // 得到上下文中的图片
    165         UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
    166         
    167         // 结束上下文
    168         UIGraphicsEndImageContext();
    169         
    170         // 4.回到主线程显示图片
    171         dispatch_async(dispatch_get_main_queue(), ^{
    172             self.imageView.image = fullImage;
    173         });
    174     });
    175 }
    176 
    177 @end
  • 相关阅读:
    maven mirrorOf
    使用nexus 搭建本地 maven 服务器
    django 访问静态资源
    django 异常问题总结
    django导入 views.py
    vue js 实现 树形菜单
    vue.js 基础
    css之margin
    Vue项目笔记
    eslint ":"号
  • 原文地址:https://www.cnblogs.com/oc-bowen/p/5137635.html
Copyright © 2011-2022 走看看