// // ViewController.m // BlockTest // // Created by CoderHJChao on 8/13/15. // Copyright (c) 2015 CoderHJChao. All rights reserved. // #import "ViewController.h" @interface ViewController () { NSString *_name; // 名字 } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; /* 1.简单为block赋值 _testBlock = ^(id sender) { NSLog(@"我是全局block类型,__NSGlobalBlock__"); }; */ /* 2.ARC上引用外部变量 int i = 100; _testBlock = ^(id sender) { NSLog(@"我是堆block类型, i%d,__NSMallocBlock__",i); }; NSLog(@"block %@",^(id sender) { NSLog(@"我是堆block类型, i%d,__NSMallocBlock__",i); }); NSLog(@"block %@",_testBlock); */ /* 3.MRC上引用外部变量 int i = 100; _testBlock = [^(id sender) { NSLog(@"我是栈block类型, i%d,__NSStackBlock__",i); } copy]; */ /* 4.ARC上引用外部变量*/ // __block ViewController *weakSelf = self; __block typeof(self) weakSelf = self; _testBlock = ^(id sender) { [weakSelf setStringName:@"nana"]; }; /* 总结: 1.block是一个对象,因为它也有OC里面的isa指针 2.block是匿名函数,它是基于C的函数拓展,它是一个函数指针 3.block是通过闭包传值,用于异步处理及方法回调、 4.block在内存中分三种类型,分别是 全局block,堆block,栈block 4.1 如果block没有引用外部变量的时候是全局block(__NSGlobalBlock__) 4.2 如果引用外部变量的话,block的初始化是在栈上, 一般我们在ARC上使用的Block是堆block(__NSMallocBlock__),因此在ARC上编译器自动把block拷贝到堆上 4.3 如果引用外部变量的话,block的初始化是在栈上, 我们在MRC上使用的Block就是栈block(__NSStackBlock__),如果block出了栈的作用域外,block就会被自动释放。如果要在堆作用域中使用block,必须要把block手动拷贝到堆上 5. block 容易导致循环引用 因为外部对象引用了block,block内部又引用外部对象,所以导致循环引用。 解决方法:在ARC上,我们可以使用weak关键字作为破解循环引用;但在MRC上,我们可以用__block关键字破解循环引用; 可以让block弱引用内部的变量,从而在释放的时候先断开弱引用,在释放block与外部的 Strong 跟 weak的区别是什么? strong引用,引用计数加一,两个对象生命周期就会绑定在一起 */ } // 改变全局变量 - (void)setStringName:(NSString *)name { _name = name; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; NSLog(@"%@",_testBlock); } @end
时间: 2024-11-09 04:37:09