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的使用及循环引用的解决的更多相关文章

  1. block(六)循环引用-b

    在ARC与非ARC环境下对block使用不当都会引起循环引用问题,一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.theBloc ...

  2. C#项目间循环引用的解决办法,有图有真相

    C#项目间循环引用的解决办法,有图有真相 程序间的互相调用接口,c#禁止互相引用,海宏软件,20160315 /// c#禁止互相引用,如果项目[订单]中有一个orderEdit单元,要在项目[进销存 ...

  3. IOS block 循环引用的解决

    在介绍block循环引用前我们先了解一下typeof. typeof是什么??? typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型. 它返回值是一个字符串,该字符串说明运算数的类 ...

  4. block中如何避免循环引用

    使用 weak–strong dance 技术 block 可以直接引用 self,但是要非常小心地在 block 中引用 self.因为在 block 引用 self,可能会导致循环引用.如下例所示 ...

  5. 关于Block的copy和循环引用的问题

    http://blog.csdn.net/felix9/article/details/9619313 在实际开发中,发现使用Block有着比delegate和notification更简洁的优势.于 ...

  6. Block的copy和循环引用的问题

    在实际开发中,发现使用Block有着比delegate和notification更简洁的优势.于是在目前的项目中大量的使用block. 在我的头文件我是这样声明使用block的. 我将block声明为 ...

  7. block的用法和循环引用

    一.block在OC中的用法可以分为大概一下几种. 1>用于成员属性,保存一段代码,可以替代代理传值. 比如说,创建一个ViewController控制器,点击屏幕就跳转到ModalViewCo ...

  8. iOS - Block产生Memory Leaks循环引用导致的内存泄漏以及解决方案

    在ARC(自动引用技术)前,Objective-c都是手动来分配释放 释放 计数内存,其过程非常复杂. ARC技术推出后,貌似世界和平了很多,但是其实ARC并不等同于Java或者C#中的垃圾回收,AR ...

  9. block使用小结、在arc中使用block、如何防止循环引用

    引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...

随机推荐

  1. call方法和new对象的关系

    call只能改变this的指向,而使用new对象不仅会自动调用call方法改变这个对象的this指向,而且还会继承构造函数的原型. var fn = function(a){ this.a = a; ...

  2. protobuf-net

    protobuf是google的一个开源项目,可用于以下两种用途: (1)数据的存储(序列化和反序列化),类似于xml.json等: (2)制作网络通信协议. 源代码下载地址:https://gith ...

  3. vs2010设置

    解决方案管理器文件自动定位:工具--选项--项目和解决方案--常规--在解决方案资源管理器中跟踪活动项(前打勾). VAssistX拼写错误的下划波浪线去掉:在VAssistX菜单栏->Visu ...

  4. WP8 SqlCE和SqlLite数据存储性能比较

    在平时的开发中一定会用到本地数据存储,除了独立存储外我们还可以选择SqlCE和SqlLite:于是在选择上我们就必须权衡他们两者的性能择优选择. 测试代码:(这个例子是在msdn sqllite例子上 ...

  5. codeforces MUH and Cube Walls

    题意:给定两个序列a ,b, 如果在a中存在一段连续的序列使得 a[i]-b[0]==k, a[i+1]-b[1]==k.... a[i+n-1]-b[n-1]==k 就说b串在a串中出现过!最后输出 ...

  6. DDD:聊天笔记

    聚合跟和实体 聚合根是实体. 实体有生命周期,使用标识进行跟踪. 聚合根是全局标识,由仓储或其它服务负责其生命周期. 实体是局部标识,由聚合根负责其生命周期. 为什么能应对复杂度? 纵向.横向.时间维 ...

  7. Java魔法堂:初探MessageFormat.format和ChoiceFormat

    一.前言 刚开始从.net的转向java的时候总觉得 String.format 用得不习惯,希望格式模版会这样 {}, }$s,$s's cat.%2$s,this is %1$s's dog. . ...

  8. C# WinFrom 跨线程访问控件

    1.跨线程访问控件委托和类的定义 using System; using System.Windows.Forms; namespace ahwildlife.Utils { /// <summ ...

  9. 循序渐进开发WinForm项目(3)--Winform界面层的项目设计

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  10. 介绍两种风格的URL

    两种风格的“动态资源”——统一资源定位符(Uniform Resource Lactor,URL) 当前互联网上主要有两种主要风格的URL: 第一种直接在URL中知名文件(比如xxx.php,xxx. ...