iOS block从浅到深的学习 以及循环引用的问题
来源:互联网 发布:美国农业数据 美元指数 编辑:程序博客网 时间:2024/06/09 18:41
1.第一部分 定义和使用Block,
<span style="font-size:14px;">// 1. 定义无参无返回值得Block void (^printBlock) () = ^() { NSLog(@"no number"); }; printBlock(); // 2. 定义名字为myBlock的代码块, 返回值类型为int int multiplier = 4; int (^ myBlock)(int) = ^(int num) { return num * multiplier; }; myBlock(5); // 3. 一个有参数没有返回值得block void (^ printsBlock)(int, int) = ^(int num1, int num2) { NSLog(@"%d", num1 + num2); }; printsBlock(2, 34);</span>
定义Block变量, 就相当于定义了一个函数, 但是区别也很明显, 因为函数肯定在-viewDidload方法外面定义, 而Block变量定义在了viewDidload方法内部, 当然,我们也可以把Block定义在外部,
再来看看上面代码运行的顺序问题, 只有调用block的时候才会执行block块内部的代码,这根函数差不多,所以有如下结论:
1.在类中,定义一个Block变量, 就像定义一个函数
2.Block可以定义在方法内部, 也可以定义在方法外部
3. 只有调用block时候, 才会执行block体内的代码
那么在类中定义一个Block, 可以当做一个私有函数, Block相当于代理, 本类中Block就相当于类自己服从某个协议, 然后让自己代理自己去做某个事情,
Block很多的用处是跨越两个类来使用的, 比如作为property属性或者作为方法的参数, 这样就可以跨越两个类
2.第二部分 Block循环引用的问题
_block关键字的使用
在block代码块中是不可以对外面的变量进行更改的,比如下面的语句
<span style="font-size:14px;">// 用__blok修饰变量, 那么在block块内可修改该变量 __block int a = 100; int (^ BlockOnew)(int) = ^(int num) { a += num; return a; }; BlockOnew(4);</span>
__weak关键字的使用
block在copy时都会对block内部用到的对象进行强引用使对象引用计数加1,对block使用不当就会引起循环引用的问题,一帮表现为, 某个类将block作为自己的属性变量, 然后该类在block的方法里面又使用了该类本身, 简单来说就是self.block = (^Type var){self something; 在block中使用了self} ;block这种循环引用会被编译器捕捉到及时提醒,
只有你在block代码块里用到了self里面的东西,就会出现循环引用的问题
ARC环境下可以通过使用__weak声明一个代替self的新变量代替原来的self,我们可以命名为weakSelf.通过这种方式告诉block,不要再block内部对self进行强制strong引用
<span style="font-size:14px;">// 用__weak修饰self 避免循环引用 __weak typeof(self) weakSelf = self; int (^ BlockOnew)(int) = ^(int num) { UIView *view = weakSelf.view; };</span>
3.第三部分:Block作为property属性实现页面之间传值
需求:在ViewController中,点击Button,push到下一个页面NextViewController,在NextViewController的输入框TextField中输入一串字符,返回的时候,在ViewController的Label上面显示文字内容
(1)第一种方法:首先看看通过“协议/代理”是怎么实现两个页面之间传值的吧,
<span style="font-size:14px;">//NextViewController是push进入的第二个页面//NextViewController.h 文件//定义一个协议,前一个页面ViewController要服从该协议,并且实现协议中的方法@protocol NextViewControllerDelegate <NSObject>- (void)passTextValue:(NSString *)tfText;@end @interface NextViewController : UIViewController@property (nonatomic, assign) id<NextViewControllerDelegate> delegate; @end //NextViewController.m 文件//点击Button返回前一个ViewController页面- (IBAction)popBtnClicked:(id)sender { if (self.delegate && [self.delegate respondsToSelector:@selector(passTextValue:)]) { //self.inputTF是该页面中的TextField输入框 [self.delegate passTextValue:self.inputTF.text]; } [self.navigationController popViewControllerAnimated:YES];}</span>
<span style="font-size:14px;">//ViewController.m 文件@interface ViewController ()<NextViewControllerDelegate>@property (strong, nonatomic) IBOutlet UILabel *nextVCInfoLabel; @end//点击Button进入下一个NextViewController页面- (IBAction)btnClicked:(id)sender{ NextViewController *nextVC = [[NextViewController alloc] initWithNibName:@"NextViewController" bundle:nil]; nextVC.delegate = self;//设置代理 [self.navigationController pushViewController:nextVC animated:YES];} //实现协议NextViewControllerDelegate中的方法#pragma mark - NextViewControllerDelegate method- (void)passTextValue:(NSString *)tfText{ //self.nextVCInfoLabel是显示NextViewController传递过来的字符串Label对象</span>
这是通过协议代理来实现两个页面之间传值的方式
2)第二种方法:使用Block作为property,实现两个页面之间传值,
先看看NextViewController文件中的内容,
<span style="font-size:14px;">//NextViewController.h 文件@interface NextViewController : UIViewController@property (nonatomic, copy) void (^NextViewControllerBlock)(NSString *tfText); @end//NextViewContorller.m 文件- (IBAction)popBtnClicked:(id)sender { if (self.NextViewControllerBlock) { self.NextViewControllerBlock(self.inputTF.text); } [self.navigationController popViewControllerAnimated:YES];}</span>
再来看看ViewController文件中的内容,
<span style="font-size:14px;">- (IBAction)btnClicked:(id)sender{ NextViewController *nextVC = [[NextViewController alloc] initWithNibName:@"NextViewController" bundle:nil]; nextVC.NextViewControllerBlock = ^(NSString *tfText){ [self resetLabel:tfText]; }; [self.navigationController pushViewController:nextVC animated:YES];}#pragma mark - NextViewControllerBlock method- (void)resetLabel:(NSString *)textStr{ self.nextVCInfoLabel.text = textStr;}</span>
这几行代码就可以用Block实现俩个VC的传值目的,实际上就取代了Delegate的功能
部分内容来自:http://my.oschina.net/leejan97/blog/268536
- iOS block从浅到深的学习 以及循环引用的问题
- iOS Block的循环引用问题
- iOS中Block的循环引用问题
- iOS中block的循环引用问题
- block 循环引用的问题
- Block的循环引用问题
- Block的循环引用问题
- block的循环引用问题
- Block的循环引用问题
- Block的引用循环问题
- block循环引用的问题
- IOS Block循环引用的内存泄漏问题
- iOS 中关于block 的循环引用问题
- iOS开发——Block循环引用问题的解决
- iOS中Block的引用循环问题 (ARC & non-ARC)
- iOS 解决block中self的循环引用问题
- ios block循环引用问题
- ios block循环引用问题
- Codeforces 658A Bear and Reverse Radewoosh
- http://imysql.cn/tag/pxc
- 底部切换按钮LuseenBottomNavigation
- android 沉浸模式(状态栏透明 跟随布局颜色)
- HOG:从理论到OpenCV实践
- iOS block从浅到深的学习 以及循环引用的问题
- 在shell下使用mysql方法
- js实现浏览器通知功能
- iOS之解决UITableView与背景颜色不一致问题
- iOS提交应用至App Store流程及真机调试 一,证书、配置文件
- 排序算法--插入排序法
- Android apk多渠道 打包
- js render
- JavaScript——Div和Span的区别