ios objective-c block

简介
Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。
用Apple文档的话来说,A block is an anonymous inline collection of code, and sometimes also called a “closure”.
1. block的定义形式
返回值 (^block的名称)(参数类型,参数类型.……)= ^(参数列表 ){
//doSomething;
};
2. block的分类
根据Block中是否引用了自动变量,可以将Block存储区域分类:
- _NSConcreteGlobalBlock-存储在全局数据区域(和全局变量一样)
- _NSConcreteStackBlock-存储在栈上
- _NSConcreteMallocBlock-存储在堆上
1). _NSConcreteGlobalBlock
BLOCK代码块不使用局部变量,使用globle变量,或者static变量

    int main(){
      @autoreleasepool{
        void (^test)() = ^(){
          NSLog(@"%@",@"testblock");
        };  
        NSLog(@"%@",test);// 打印出 <__NSGlobalBlock__: 0x10c8da050>
      } 
      return 0 ; 
    }

2). _NSConcreteStackBlock
BLOCK代码块使用局部变量时

        int main(){
          @autoreleasepool{
            int a = 1;
            void (^test)() = ^(){
              NSLog(@"%@%d",@"testblock",a);
            };  //MRC环境,在ARC环境返回MallocBlock
            NSLog(@"%@",test);// 打印出 <__NSStackBlock__: 0x7fff563f2ba8>
          } 
          return 0 ; 
        }

3). _NSConcreteMallocBlock

        int main(){
          @autoreleasepool{
            int a = 1;
            void (^test)() = [^(){
              NSLog(@"%@%d",@"testblock",a);
            }copy];
            NSLog(@"%@",test); //打印 <__NSMallocBlock__: 0x7fab13d02a90>
          }

          return 0 ; 
        }

3 变量读取与修改(ARC环境)

3.1 基本数据类型

3.1.1 全局变量

    修改不需要__block修饰

3.1.2 静态变量

    修改不需要__block修饰

3.1.3 局部变量

    修改需要__block修饰

3.2 对象
3.2.1 全局指针变量
可以直接修改指针值,block_copy()不增加全局变量的引用计数

NSString *str;//全局变量 
-(void)bb{

    str = [[NSString alloc] initWithFormat:@"aa"];

    void (^test)() = ^(){

        NSLog(@"%@",str);//不增加引用计数

    };
    test();//打印出 aa,str的引用计数为1

    str = nil;
    test();//打印出 (null)

    return;
}

3.2.2 静态指针变量

可以直接修改指针值,block_copy()不增加全局变量的引用计数,同3.2.1.

3.2.3 局部指针变量
不用__block,__weak修饰,

    -(id)bb{

    NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];

    void (^test)() = ^(){

        NSLog(@"%@",str);

    };
    test();//打印 aa
    str = nil;
    test();//打印 aa
    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];
    test();//打印 aa

}

多个变量指向同一对象的引用计数

    -(id)bb{

    NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];
    NSString *str1 = str;
    void (^test)() = ^(){
        NSLog(@"%@",str);//引用计数+1
        NSLog(@"%@",str1);//引用计数+1

    };
    test();//打印 aa
    str = nil;
    test();//打印 aa
    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];
    test();//打印 aa ,同时str的retainCount=2

}

__block修饰
__block修饰的对象在栈展开后才对外部变量增加引用计数。看代码,

-(id)bb{

    __block NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];
    void (^test)() = ^(){

        NSLog(@"%@",str);//未增加引用计数 

    };
    test();//打印 aa
    str = nil;
    test();//打印(null)
    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];//展开后才对外部引用对象增加引用计数
    test();//打印(null)
  }

-(id)bb{

    __block NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];
    void (^test)() = ^(){

        NSLog(@"%@",str);

    };
    test();//打印 aa

    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];
    test();//打印 aa
  }

__weak修饰

-(id)bb{

    NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];
    __weak NSString *wStr = str;

    void (^test)() = ^(){

        NSLog(@"%@",wStr);//不增加引用计数

    };
    test();
    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];
    test();//打印(null)

}

Weak-Strong Dance 避免循环引用,并保证代码执行一致

-(id)bb{

    NSString *str;
    str = [[NSString alloc] initWithFormat:@"aa"];
    __weak NSString *wStr = str;

    void (^test)() = ^(){
        NSString *ss = wStr;//block_copy()时不增加引用计数,执行时如果 wStr!=nil,则会强引用该对象,防止在多线程环境下,代码执行一半时,对象被释放,导致结果出错。

        if (ss){
            NSLog(@"%@",ss);
            NSLog(@"%@",ss);
        }

    };
    test();
    return test;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    void (^test)() = [self bb];
    test();//打印(null)

}

参考
http://my.oschina.net/leejan97/blog/268536
http://www.cnblogs.com/biosli/archive/2013/05/29/iOS_Objective-C_Block.html
http://www.cocoachina.com/ios/20150109/10891.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值