block 与 gcd

1.block 

block 的定义 回传值 (^名字) (参数列);

主要分成3部分 返回值  名称 和参数。 当没有的时候 可以省略。

 int (^ myinttest)(int) = ^(int a){
        return  -a;
    };
    int a = myinttest(100);
    NSLog(@"%d",a);

一般情况下 最好 用 typedef 申明一下别名 方便使用也方便理解。

typedef int (^ negative)(int);
    negative getNegative = ^(int a){
        return  -a;
    };
    int a = getNegative(100);
    NSLog(@"%d",a);

重点是 block 访问外部的变量

block内部对于外部的访问。其实是复制一份。就类似java的传参。对于基本类型。是值传递(复制一份)。对于对象(指针)传递的是指针的备份。注意 这里复制的对象是只读的。不可以修改

想要修改外部变量就需要用到__block。

在这里需要注意 原本是在栈上面的变量(基本类型)需要copy到堆上面去。如果使用了__block的话。会将外部变量的地址变成新的堆上面的地址。


2.gcd

概念啥的就不写了没意识直接进入主题。
首先需要明白 2组概念
同步提交队列   dispatch_sync/dispatch_sync_f   
block执行完。方法才会返回。
异步提交队列   dispatch_async/dispatch_async_f
不等block执行完就方法就返回

并行队列  队列中多个线程一起执行
串行队列  同一时间只执行

然后从队列开始说起。在我的学习以及工作中。就三种队列:

1.全局队列  

这个是一个默认实现的并发队列。我们在大多数需要后台执行的逻辑。可以放入这个队列中;
方法  dispatch_get_global_queue( long identifier, unsigned long flags);
第一个参数是 优先级 有四个优先级
 DISPATCH_QUEUE_PRIORITY_HIGH:         
 DISPATCH_QUEUE_PRIORITY_DEFAULT:     
DISPATCH_QUEUE_PRIORITY_LOW:         
DISPATCH_QUEUE_PRIORITY_BACKGROUND:  
实际上我跟人不赞同过度使用这4个优先级。如果真的有这方面逻辑 还是自定义队列等来实现吧。
第二个参数是 预留的 。写死0;

2.主队列

 dispatch_get_main_queue()

这个就是更新ui的串行队列。是先进先出。一个接着一个执行的队列。要跟前台交互,更新ui需要加入这个队列。

3.自己创建队列

dispatch_queue_t myqueue =dispatch_queue_create("com.aurora.test",DISPATCH_QUEUE_CONCURRENT);

第一个参数是一个附带的字符串。可以为nil 。这个主要是给调试工具使用的。可以理解为这个队列的名字;不易理解为队列的 id。 不决定 队列的唯一性。自己命名的时候 要去不相同的。即使取相同的 也是2个队列。

第二参数就是队列的类型:

DISPATCH_QUEUE_CONCURRENT  并行

DISPATCH_QUEUE_SERIAL  串行

总之 GCD 的使用理解清楚2个: 

1 。请求是分同步调用 和异步调用 。 看方法名称可以看出来。 

2 。队列是分串行 并发

下面 有一些扩展:

dispatch_after

 是延后一定的时间 激活队列。注意的是 并不是 表示 多少时间之后 一定执行。可以理解为 一定的时间后将这个任务加到队列里面去。至于什么时候执行。需要看队列的情况了。

dispatch_after(time, myqueue, ^{
    });
使用方法如上。多了第一个参数 表示的时间

dispatch_time_t time =  dispatch_time(DISPATCH_TIME_NOW, (int64_t)1 * NSEC_PER_SEC);
构建时间参数 第一个参数看名字就知道 是现在。 第二个参数是时间 是 毫微秒(十亿分之一秒)系统定义了几个常量。 所以乘以这些常量就ok了。

注意  dispatch_after 是 异步调用的。所以不需要等待block执行完毕就返回;

dispatch_apply

这个是指重复多少次 

    dispatch_apply(10, myqueue, ^(size_t i) {
        
    });
这个就是加入10个到队列中去。这个 调用是同步的 。需要等十次执行完 才会返回.

dispatch_once

保证队列只执行一次

 static dispatch_once_t onece;
 dispatch_once(&onece, ^{
        NSLog(@"my one");
    });

第一个参数 就是一个 long 数字。必须初始化成0. 当执行完了之后 会变成 -1.。

dispatch_barrier_async/dispatch_barrier_sync

这个 是栅栏 。 含义就是 保证在执行这块代码的时候。 这个队列里面没有其他代码在执行。毫无疑问 只有并发队列 中。才有意义。 举例来说当这block加入到队列中的时候。还有任务在执行。就会 等这些都执行玩再执行栅栏。 在执行栅栏的时候 也不会有其他block 执行。

dispatch_group

这个是分组。对于一些队列 你可能希望将他们分为一组进行操作。也需需要等这一组执行玩后 做一些逻辑。这时候 这个就有大作用了。

    dispatch_queue_t myqueue = dispatch_queue_create("com.aurora.test", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_t mygroup = dispatch_group_create();
   
    dispatch_group_async(mygroup, myqueue, ^{
        [NSThread sleepForTimeInterval:4];
        NSLog(@"111");
    });
    dispatch_group_notify(mygroup, dispatch_get_main_queue(), ^{
        NSLog(@"all end");
    });
    dispatch_group_async(mygroup, myqueue, ^{
         [NSThread sleepForTimeInterval:5];
        NSLog(@"222");
    });
   

这样 在一个 group 中执行的 代码 都完事的时候 就将notify 加入到 指定的队列中去;

也可用 

dispatch_group_enter 

dispatch_group_leave

dispatch_group_wait

组合使用 来达到这个目的 不过 wait 是 会阻塞线程的 这个需要注意

    dispatch_queue_t myqueue = dispatch_queue_create("com.aurora.test", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_t mygroup = dispatch_group_create();
   
    dispatch_group_async(mygroup, myqueue, ^{
        dispatch_group_enter(mygroup);
        [NSThread sleepForTimeInterval:4];
        NSLog(@"111");
        dispatch_group_leave(mygroup);
    });
//    dispatch_group_notify(mygroup, dispatch_get_main_queue(), ^{
//        NSLog(@"all end");
//    });
    dispatch_group_async(mygroup, myqueue, ^{
        dispatch_group_enter(mygroup);
         [NSThread sleepForTimeInterval:5];
        NSLog(@"222");
         dispatch_group_leave(mygroup);
    });
    dispatch_group_wait(mygroup, DISPATCH_TIME_FOREVER);
    NSLog(@"end");



你可能感兴趣的:(ios)