Block总结

BLOCK

block的描述: 他是类似函数指针的一个代码块的内联封装, 他可以将一个函数体作为对象传递

block的本质: 对象

block的效率: 高于函数调用


声明一个block

           返回值 (^名称)(以”逗号”分割的参数), 参数部分可以不写参数名只写类型

范例:

              void  (^myFirstBlock)( int a, NSString *s, UIButton *button )

            BOOL (^mySecondBlock)(void)

    NSString * (^myThirdBlock)(CGFloat, float)


定义一个block

         ^可省略的返回值(以”逗号”分割的参数){代码块}

范例:

        ^void(int a){NSLog(@"一个int参数, 无返回值的block"); } 

        ^{ NSLog(@"一个无参数,无返回值的block"); }                

        ^int(int a, int b){ NSLog( @"一个两个int参数, 返回两个数相加的block, 结果%d", a + b ); return a + b; }


block作为函数参数

         block作为参数, 参数名后缀, 类型格式为: ( 返回值(^)(参数) )block名 

范例:

- (void)test:(int(^)(int))paramBlock

{

        NSLog( @"打印block返回结果:%d", paramBlock(10));

}


 block作为参数的函数调用:

         将block定义部分或将block对象传入函数调用的参数部分

范例:

[self test:^(int a){

        return a * a;

}];


__block:

block只能只读的访问局部变量, 若需要修改局部变量, 需要通过__block修饰该变量, 该修饰符会使block自动复制该对象的指针,即指针拷贝, 当对该对象执行写操作时, 其实就是操作其指针指向的对象进行操作.

若不加该修饰符, block仅自动复制需要访问的局部变量的值副本(值拷贝), 因此只能进行只读操作.

__weak:

使用block特别要注意的一点就是防止循环引用的发生, block作为一个对象被持有者持有,若block内部也持有该持有者将会导致循环引用,导致相互持有, 永远无法销毁彼此的内存问题, 若不能规避该问题, 则需要通过使用__weak修饰 block要访问的持有者变量, 防止循环引用的发生. 尤其是block所在的self.

__strong

该修饰符在block内的主要作用是防止__weak修饰的指针在block运行期间被外部销毁, 导致block无法顺利完成原定功能. 所以当访问的外部变量用__weak修饰时, block内部最好再有一个__strong修饰的同类型指针指向__weak指针, 这样就可以确保, 在block内部的这个指针可以运行完成. 随着block运行完成, __strong修饰的指针也将自动销毁, 进而__weak指针也会自动置nil.


block外部变量访问

block可以访问和修改全局变量

block只能只读的访问局部变量(值传递, block内部复制了一个副本), 若加了__block修饰, 就改为引用传递,可修改局部变量


block底层浅谈

block本身包含一个结构体

struct __block_impl

{

void *isa;

int Flags;

int Reserved;

void *FuncPtr;

}

block分为三种类型, __block_impl的isa指针负责标记block类型

_NSConcreteGlobalBlock: 全局静态block, 当block内不访问任何外部变量, 或者访问的是全局作用域,成员变量的, 属于该类型, 内存管理方式和函数一致

_NSConcreteStackBlock 栈block, 由系统管理内存, 函数返回时销毁, 访问的外部变量由block从栈上copy到堆上, 保证了作用域结束后, block仍然可以访问

_NSConcreteMallocBlock 堆block, 由开发者控制, 引用计数为0时销毁


block几种自身copy的情况, 若触发一下情况, block将自动拷贝自身到堆中, 确保自身作用域内的变量的生命周期更长久

1.显式执行copy, [block copy];

2.block作为返回值的时候

3.block被赋值给__strong类型的对象或者block的内部变量时

4.block作为参数传入带有usingBlock的CocoaFramework方法

5. block作为参数传入GCD的API时


其他:

__typeof, __typeof__, typeof 这三个关键字实现了一个相同的功能, 获取参数的类型名称并返回

UIViewController *vc;

__typeof(vc) vc2;

这样就可以在不知道vc指针类型的情况下, 再声明一个同类型的vc2

你可能感兴趣的:(Block总结)