Block的使用及循环引用的解决
Block是一个很好用的东西,这篇文章主要来介绍:1.什么是Block?2.Block的使用?3.Block的循环引用问题及解决.
1.什么是Block?
说这个问题之前,我先来说一下闭包(Closure)。闭包就是一个函数,或者一个指向函数的指针,加上这个函数执行的非局部变量。说的通俗一点,就是闭包允许一个函数访问声明该函数运行上下文中的变量,甚至可以访问不同运行上文中的变量。
Block实际上就是OC语言对闭包的实现。
下面声明一个Block:
int (^Sum)(int, int);
首先,第一个int也就是该Block的返回值类型,也可以是其他的返回值类型,或者无返回值。“^”是Block的标识。第二以及第三个int,则是Block的参数类型,当然也可以无参数。
下面的代码则是定义了一个Block,当执行Line5代码时,会输出“nihao”,也就是给Block传入的参数。
void (^printBlock)(NSString *) = ^(NSString *str) {
NSLog(@"%@", str);
};
printBlock(@"nihao");
下面借鉴一张网上流传的图片总结一下Block的结构:

需要说明的是,Block能够直接修改和访问全局变量,但是只能访问局部变量,如果想要在Block中修改局部变量,使用 __block 修饰即可。关于Block的基本介绍就是这么多了。有需要的tx可以留言,再做适当的更新。下面简单说说Block的使用。
2.Block的使用
2.1 使用Block在不同的页面进行传值
页面传值有很多方式,比如:属性、单例、通知、代理,Block等。这里单说使用Block传值,其他几种以后再做补充。
使用Block传值也有两种方式:Block属性和使用Block作为参数的方法。
2.1.1 使用Block属性传值
下面演示的是从B页面(后一个页面)传值到A页面(前一个页面)。
首先在B页面中声明一个Block,通常为了使代码简洁,我一般会对Block进行重定义:
typedef void (^PassVal)(NSString *text);
接着,在B中声明一个Block属性:
@property (nonatomic, copy) PassVal passVal;
这里需要注意下,我使用了copy,实际上在ARC环境下,使用copy和strong都是可行的。我这里只是为了表明,使用Block时,实际上是把Block从栈区拷贝到了堆区。
下面继续。我这里选择在B页面即将消失时,将值传出:
- (void)viewWillDisappear:(BOOL)animated {
if (self.passVal) {
self.passVal(@"");
}
}
我们可以看一下前面声明的Block是一个有参(string类型),无返回值。这里我给Block的参数是@"123456798"。通过上面的处理,B页面的操作已经完成了。下面进行A页面的操作:
- (void)btnNextAction:(UIButton *)btnNext {
BViewController *BVC = [[BViewController alloc] init];
BVC.passVal = ^(NSString *text) {
NSLog(@"%@",text);
};
[self.navigationController pushViewController:BVC animated:YES];
}
上面的代码演示了,在点击按钮即将push到B页面时,来实现Block。这样就可以在A页面中得到B页面的值,也就是text值。到此,Block属性传值结束。
2.1.2 使用带有Block参数的方法传值
这种方式和属性传值类似,下面做简单的示例:
typedef void (^PassVal)(NSString *text); @interface SecondViewController : UIViewController @property (nonatomic, copy) PassVal passVal; - (void)returnText:(PassVal)block; @end
首先在第二个页面同样需要声明Block属性,同时在第二个页面声明一个方法,方法的参数即是属性同样类型的Block。接着实现下面的方法:
- (void)viewWillDisappear:(BOOL)animated {
if (self.passVal) {
self.passVal(@"");
}
}
- (void)returnText:(PassVal)block {
self.passVal = block;
}
首先要做的还是先给Block的参数赋值,接着要实现声明的方法。接下来去第一个页面操作:
- (void)btnNextAction:(UIButton *)btnNext {
SecondViewController *secCtr = [[SecondViewController alloc] init];
[secCtr returnText:^(NSString *text) {
NSLog(@"%@",text);
}];
[self.navigationController pushViewController:secCtr animated:YES];
}
这样也可以实现传值。
使用方法传值,猛一看觉得挺麻烦,但是实际上,使用方法调用的方式是很容易理解的。
传值只是Block的简单应用,总体来说,Block和代理的使用时很类似的,可以互相参考着学习。
3.Block的循环引用问题及解决.
首先我们需要明确的是,一个对象的Block属性是使用copy来修饰,当Block被copy时,会对block中用到的对象产生强引用(ARC)或者引用计数加一(MRC)。当我们使用Block时,如果Block方法又引用了对象,如使用 self. 来引用对象的属性,这就会造成循环引用。其实如果产生了循环引用我们也不需要很担心,因为编译器会自动提醒,只需要在提醒的时候进行处理就可以了.一般在ARC下可以这么处理(仅作为示例用法):
__weak typeof(self)weakSelf = self;
[self.tableView addHeaderWithCallback:^{
weakSelf.isDown = YES;
weakSelf.page = ;
[weakSelf requestData];
}];
也就是说,把需要使用self的地方换成weakSelf即可.如果是MRC,只需要把上面代码的第一行更换为:
__block typeof(self)weakSelf = self;
以上仅作为各位使用的参考,如果有不到位的地方,欢迎各位留言指出,大家一起交流.
Block的使用及循环引用的解决的更多相关文章
- block(六)循环引用-b
在ARC与非ARC环境下对block使用不当都会引起循环引用问题,一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.theBloc ...
- C#项目间循环引用的解决办法,有图有真相
C#项目间循环引用的解决办法,有图有真相 程序间的互相调用接口,c#禁止互相引用,海宏软件,20160315 /// c#禁止互相引用,如果项目[订单]中有一个orderEdit单元,要在项目[进销存 ...
- IOS block 循环引用的解决
在介绍block循环引用前我们先了解一下typeof. typeof是什么??? typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型. 它返回值是一个字符串,该字符串说明运算数的类 ...
- block中如何避免循环引用
使用 weak–strong dance 技术 block 可以直接引用 self,但是要非常小心地在 block 中引用 self.因为在 block 引用 self,可能会导致循环引用.如下例所示 ...
- 关于Block的copy和循环引用的问题
http://blog.csdn.net/felix9/article/details/9619313 在实际开发中,发现使用Block有着比delegate和notification更简洁的优势.于 ...
- Block的copy和循环引用的问题
在实际开发中,发现使用Block有着比delegate和notification更简洁的优势.于是在目前的项目中大量的使用block. 在我的头文件我是这样声明使用block的. 我将block声明为 ...
- block的用法和循环引用
一.block在OC中的用法可以分为大概一下几种. 1>用于成员属性,保存一段代码,可以替代代理传值. 比如说,创建一个ViewController控制器,点击屏幕就跳转到ModalViewCo ...
- iOS - Block产生Memory Leaks循环引用导致的内存泄漏以及解决方案
在ARC(自动引用技术)前,Objective-c都是手动来分配释放 释放 计数内存,其过程非常复杂. ARC技术推出后,貌似世界和平了很多,但是其实ARC并不等同于Java或者C#中的垃圾回收,AR ...
- block使用小结、在arc中使用block、如何防止循环引用
引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...
随机推荐
- NVIDIA CuDNN 安装说明
CuDNN是专门针对Deep Learning框架设计的一套GPU计算加速方案,目前支持的DL库包括Caffe,ConvNet, Torch7等. CuDNN可以在官网免费获得,注册帐号后即可下载.官 ...
- Unity3D 纹理偏移(TextureOffset)浅析
首先,给出圣典的解释: Material.mainTextureOffset 主纹理偏移量 var mainTextureOffset : Vector2 Description描述 The text ...
- JS&CSS文件请求合并及压缩处理研究(二)
上篇交待了一些理论方面的东西,并给出了另外一种解决方案的处理流程.本篇将根据该处理流程,开始代码方面的编写工作. 1,打开VS,新建ASP.NET MVC Web项目,项目类型选择空.名称为 Mcmu ...
- 探秘重编译(Recompilations)(1/2)
这篇文章我想谈下SQL Server里一个非常重要的性能调优话题:重编译(Recompilations) .当你执行非常简单的存储过程(使用临时表)时,就会发生.今天我想奠定SQL Server里重编 ...
- SQL语句技巧:查询存在一个表而不在另一个表中的数据记录
方法一(仅适用单个字段)使用 not in ,容易理解,效率低 select A.ID from A where A.ID not in (select ID from B) 方法二(适用多个字段匹配 ...
- 通过Nginx实现负载均衡
百度了下负载均衡:英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器.FTP服务器.企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务 嗯,跟我理 ...
- 用Qt写软件系列四:定制个性化系统托盘菜单
导读 一款流行的软件,往往会在功能渐趋完善的时候,通过改善交互界面来提高用户体验.毕竟,就算再牛逼的产品,躲藏在糟糕的用户界面之后总会让用户心生不满.界面设计需综合考虑审美学.心理学.设计学等多因素, ...
- P6 EPPM 安装与配置指南 16 R1 2016.4
关于安装和 配置P6 EPPM 本指南告诉你如何自动 安装和配置您的应用程序. 在您开始之前,阅读 先决条件 P6 EPPM配置 (7页). 安装P6 EPPM 您将使用 安装程序 (窗口) . ...
- linq之join子句
前面我们总结Linq查询子句总共有8个,join子句是我们讲解的最后一个子句.join子句也是相对比较复杂的,所以最后来讲.join子句可以处理两个数据源之间的联系,当然这两个数据源之间必须存在相关联 ...
- C#设计模式——外观模式(Facade Pattern)
一.概述 在系统设计中,某一个系统可能非常庞大,用户要使用该系统就不得不掌握大量的接口,造成使用的不便.这时可以考虑将该系统细分成一系列子系统并使子系统间的耦合降到最低,利用外观模式提供一个外观对象, ...