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中是怎么工作的吗 ...
随机推荐
- jQuery+Ajax滚屏异步加载数据实现(附源码)
一.CSS样式 body { font:12px/1.0em Microsoft Yahei; line-height:1.6em; background:#fff; line-height:1.2e ...
- TF-IDF 简介
假设我们手头有大量的文档(或网页), 通常我们会比较关心以下几个问题: 1. 每一个文档的关键词(或主题词)包括哪些? 2. 给定一个(或一组)关键词,与这个(或组)词最相关的文档是哪一个? 3. ...
- 受限玻尔兹曼机(RBM)学习笔记(二)网络结构
去年 6 月份写的博文<Yusuke Sugomori 的 C 语言 Deep Learning 程序解读>是囫囵吞枣地读完一个关于 DBN 算法的开源代码后的笔记,当时对其中涉及的算 ...
- Java魔法堂:注解用法详解——@Override
一.前言 现在有Son和Parent两个类,且类型Son将会重写类型Parent的getName函数.但不幸的是由于码农大意,写成如下代码: public class Parent{ public S ...
- Linux永久修改系统时间和时区方法
修改时区: 1> 找到相应的时区文件 /usr/share/zoneinfo/Asia/Shanghai 用这个文件替换当前的/etc/localtime文件. 或者找你认为是标准时间的服务器, ...
- sprint个人总结+读书博客
读书感想: 第8章讲了需求分析,在我的日常软件编写中,肯定需要需求分析的,一个没有需求的软件,编写出来也没有什么意义,只能是丢在一个角落里发霉.需求有各种各样,要怎样才能满足客户的需求呢,那就要 ...
- 实现虚拟模式的动态数据加载Windows窗体DataGridView控件 .net 4.5 (一)
实现虚拟模式的即时数据加载Windows窗体DataGridView控件 .net 4.5 原文地址 :http://msdn.microsoft.com/en-us/library/ms171624 ...
- Ubuntu 12.04下解决Tomcat自启动问题
当我们安装好Tomcat使用后发现,每次启动都需要在终端中手动键入sudo /var/tomcat/bin/startup.sh,那么我们怎么解决这个问题呢 http://hovertree.com/ ...
- 使用Windows PE的U盘安装win7
前年刚去公司的时候用PE装过好多系统,最近又装一台华硕的,碰到了一个问题,一起记录了下. 华硕X45,Bios已经改为U盘启动了,但就是进不去,因为知道可能还有个选磁盘启动项的键,找了半天原来按Esc ...
- javascript运算符的优先级
最基木的运算符优先级就是所谓的“先乘除,后加减”.对于优先顺序处于同一层次上的运算符,按照从左到右出现的顺序计算.下面给出javascript定义的所有运算符的优先级.运算符 优先顺序成员选择.括号. ...