码迷,mamicode.com
首页 > 其他好文 > 详细

block相关知识点

时间:2015-12-09 01:49:22      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

Block简介
1.Block类似于函数,指向一块代码的指针(类似C中的回调函数)Block经常用来代替delegate
2.跟函数的写法基本是一致的  声明 + 实现 + 调用
   2.1声明:^ 脱字符
                   返回类型(^Block的名字)(类型1 参数1,类型2 参数2……);
   2.2 实现:Block的名字 = ^(类型1 参数1……){  }
   2.3 调用:如果不调用,那么代码块中的内容是不会执行的,什么时候调用,就什么时候执行
                      Block的名字(参数1,参数2……);
Block基本用法
1.无返回值无参数的block
     实现的简写:
     eatBlock = ^{
     NSLog(@"我在chiFan");
     };
void (^eatBlock)();
    eatBlock = ^(){
        NSLog(@"我在chiFan");
    };
    eatBlock();
2.有参数无返回值的:写一个block输出a+b的值
void(^sumBlock)(NSInteger a,NSInteger b);
    sumBlock = ^(NSInteger a,NSInteger b){
        NSLog(@"%d + %d的值为%d",a,b,a+b);
    };
    sumBlock(20,30);
2.1 简写:声明+实现二合一,并且声明时参数的名字可省略
void(^sumBlock1)(NSInteger,NSInteger) = ^(NSInteger a,NSInteger b) {
        NSLog(@"%d + %d的值为%d",a,b,a+b);
    };
    sumBlock1(50,60);
3.有参数有返回值的block:写一个block用来求a+b的值并且把结果返回
NSInteger (^sumBlock2)(NSInteger,NSInteger) = ^(NSInteger a,NSInteger b) {
        return a+b;
    };
    NSInteger a = sumBlock2(100,200);
    NSLog(@"求和的结果为%d",a);
4.通过block修改外部变量的值
     结论:
     4.1 block内部不能修改block外部的局部变量.如果说非得改,声明时需要加上__block
     4.2 全局变量/静态变量可以修改
     4.3 block内部可以使用block外部的变量
__block int num = 10;
    void (^block1)() = ^(){
        int a = num;
        num = 20;
    };
    block1();
5.结论
  5.1 如果不用__block修饰变量,block内部使用的是对象的值
  5.2 block内部使用的值并不是a的123,它自己重新声明了一个变量b,b内容为123,将来a改变的时候,b并不会改变
  5.3 需要加上__block,通过__block的修饰,block内部使用的不再是变量a的值123,而是a的指针(a本身)
    __block int sumNum = 123;
    void (^block2)() = ^ {
        NSLog(@"%d",sumNum);
    };
    sumNum = 456;
    block2();
6. block可以当做属性来用
   结论
   6.1 声明属性只能用copy修饰
   6.2 造成循环引用
self.propertyBlock = ^{
       
    };
7.通过typedef来简化block的定义,一般来说用于简化属性的block
     typedef:定义类型
     #define:宏定义
MyInt age = 30;
    MyBlock block3 = ^{
    };
    MyBlock block4 = ^{
    };
8.block的快捷键
     inlineblock
 
    MyNewBlock aBlock = ^(int a,int b) {
        NSLog(@"aaaa");
        return  a+b;
    };
    aBlock(10,20);
Block内存管理
1.内存主要分五块
  1.1 栈(区):由编译器自动分配/释放,一般用来存放函数的参数值,局部变量的值等。
              例子:int a = 29;
     1.2 堆(区):一般由程序员分配/释放。如果说程序员不释放,程序结束时可能有OS回收
           例子:People *p = [[People alloc] init];
     1.3 全局区(静态区):全局变量/静态变量放在这个区域。初始化的全局变量/静态变量放在一个区域,未初始化的全局变量/静态变量放在另一个区域。程序结束后由系统释放。
     1.4 文字常量区:常量字符串,程序结束后系统释放 NSString *string = @“张三”;
     1.5 程序代码区:存放函数体的二进制码
2.Block本身的内存管理
   2.1MRC
        2.1.1  在MRC下,Block默认分配在“栈区”,如果离开Block所在的作用域,Block会被丢弃/释放
        2.1.2   NSGlobalBlock(如果块中没有使用外部变量):对于retain,release,copy无效
             NSStackBlock(如果块中使用了外部变量):retain,release无效,copy有效,会得到NSMallocBlock
                陷阱:如果把block添加到数组中,然后再从数组中取出的话,如果数组是自动释放的,那么在数组释放的时候里面的所有的对象都会被release
                正确:[array addObject:[[block2 copy] autorelease]];
             NSMallocBlock(NSStackBlock被copy):支持retain, release.retain/release可以增加/减少引用计数,但是block的retainCount始终为1.
             建议:不要对block使用retain操作,不方便管理
2.2 ARC
     3.block块中对象的内存
     前提:主要是针对copy的block
代码:
__block int a = 10;
    void(^block1)() = ^() {
        a = 20;
    };
    block1();
    NSLog(@"%@",[block1 copy]);

    //陷阱
    int b = 20;
    MyBlock block2 = ^() {
        NSLog(@"%d",b);
    };
    block2();
    NSLog(@"block2:%@",block2);
    NSMutableArray *array = [NSMutableArray array];
    [array addObject:[[block2 copy] autorelease]];
   
    MyBlock block3 = array[0];
    block3();
    NSLog(@"block3:%@",block3);
   
    MyBlock block4 = [block3 retain];
    NSLog(@"----%d",[block3 retainCount]);


__block People * localObj = [People new];
    staticObj        = [People new];
    gloabObj          = [People new];
    _propertyObj      = [People new];
   
    NSLog(@"%d--%d--%d--%d====%d",localObj.retainCount,staticObj.retainCount,gloabObj.retainCount,_propertyObj.retainCount,self.retainCount);
   
    /*block块中的对象
     全局变量:不变
     局部变量:通过block copy会+1 (MRC下局部变量一般需要加上__block,防止循环引用,ARC下加__weak)
     static变量:不变
     属性:不变
    
     self本身也会+1
     */
    MyBlock block5 = ^() {
        gloabObj.age = 10;
        staticObj.age = 20;
        _propertyObj.age = 30;
        localObj.age = 40;
    };
    block5();
    [block5 copy];
    NSLog(@"%d--%d--%d--%d====%d",localObj.retainCount,staticObj.retainCount,gloabObj.retainCount,_propertyObj.retainCount,self.retainCount);
Block导致循环引用的处理方法
Block导致的循环引用:针对于copy后的Block
1.Block内部使用self
1)Block内部使用self,会对self的引用计数+1
2)Block会在dealloc中释放,dealloc方法会在self释放的时候调用(self引用计数+1,dealloc方法是不会被调用)
解决办法:__block MainVC *newVC = self;
2.Block中使用全局变量也会导致循环引用
解决办法:__block NSString *newName = name;

总结:
1.Block属性中不能使用全局变量/属性,一般都转换为用__block修饰的局部变量
2.如果是局部Block,无所谓

NSTimer导致的循环引用
     解决办法:在viewDidDisappear关闭定时器
代理导致的循环引用
     解决办法:delegate用assign修饰











block相关知识点

标签:

原文地址:http://www.cnblogs.com/angelxing/p/5031521.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!