iOS开发Block的介绍以及Block的循环引用问题
1:block的循环引用问题最主要记住两点:
如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】
如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】
2:
#import "ViewController.h"
#import "XMGPerson.h" @interface ViewController ()
@property (nonatomic, copy) int (^sumBlock)(int, int);
@property (nonatomic, assign) int a;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; [self test5];
/*
如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】
如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】
*/
} /**
* 不可行
*/
- (void)test6
{
XMGPerson *p = [[XMGPerson alloc] init]; __weak XMGPerson *weakP = p; p.name = @"Jack"; p.block = ^{ // block1
XMGPerson *strongP = weakP;
NSLog(@"block1 -- %@", strongP.name); dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
NSLog(@"block2 -- %@", weakP.name);
});
}; p.block();
} /**
* 可行
*/
- (void)test5
{
XMGPerson *p = [[XMGPerson alloc] init]; __weak XMGPerson *weakP = p; p.name = @"Jack"; p.block = ^{ // block1
NSLog(@"beign-------");
XMGPerson *strongP = weakP; dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{ // block2 // NSLog(@"block2 -- %@", weakP.name);
NSLog(@"block2 -- %@", strongP.name); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // block3
NSLog(@"block3 -- %@", strongP.name);
}); });
}; p.block();
} /**
* 不可行
*/
- (void)test4
{
XMGPerson *p = [[XMGPerson alloc] init]; p.name = @"Jack"; p.block = ^{ // block1
NSLog(@"beign-------"); dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
NSLog(@"after-----------%@", p.name);
});
}; p.block();
} /**
* 不可行
*/
- (void)test3
{
XMGPerson *p = [[XMGPerson alloc] init];
__weak XMGPerson *weakP = p; p.name = @"Jack"; p.block = ^{ // block1
NSLog(@"beign-------");
XMGPerson *strongP = weakP; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
^{ // block2
NSLog(@"after-----------%@", strongP.name);
});
}; p.block();
} /**
* 可行
*/
- (void)test2
{
XMGPerson *p = [[XMGPerson alloc] init]; __weak XMGPerson *weakP = p; p.name = @"Jack";
p.block = ^{ // block1
NSLog(@"beign-------"); XMGPerson *strongP = weakP; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
^{ // block2
NSLog(@"after-----------%@", strongP.name);
});
}; p.block();
} - (void)test1
{
XMGPerson *p = [[XMGPerson alloc] init]; __weak XMGPerson *weakP = p; p.name = @"Jack";
p.block = ^{
NSLog(@"-----------%@", weakP.name);
};
} #pragma mark - 其他
- (void)test:(int (^)(int, int))sumBlock
{ } - (void)run:(int)a
{ } - (void)testBlock
{
[self test:^(int a, int b){
return a + b;
}]; void (^block)() = ^{
NSLog(@"-------");
};
block(); int (^sumBlock)(int, int) = ^(int num1, int num2){
return num1 + num2;
};
sumBlock(, ); int a = ; /*
返回值类型 (^block的变量名)(形参类型列表) = ^(形参列表) {
// block代码
};
block的变量名(实参列表);
*/
} @end
总结:1:block的定义:1:block以属性定义的时候,用copy修饰,
@property (nonatomic, copy) void (^block)();无参数无返回值,因为block默认是在堆里,需要将堆中的block,copy到栈中才能使用 2:block的非属性定义:1:无参数无返回值:
其中 void (^block)() 表示声明一个名称为block的block,block的类型表示为:void (^)(),右边的为block任务的代码块,
block();表示调用block,右边为左边的block赋值
void (^block)() = ^{
NSLog(@"-------");
};
block();
2:有参数有返回值的block:左边int (^sumBlock)(int, int)定义一个有参数有返回值的block:sumBlock,而右边的block给左边的block赋值,写法:参数写在^(int a,int b)其中ab为block的参数,返回值写在block的代码块中。
sumBlock(10, 10);调用block,并未block传递参数
^(int num1, int num2){
return num1 + num2;
};
int (^sumBlock)(int, int) = ^(int num1, int num2){
return num1 + num2;
};
sumBlock(10, 10);
3:block作为参数传递:1: block作为参数传递 - (void)test:(int (^)(int, int))sumBlock,实现该方法,调用block传递参数 2:在外部调用test方法,其中ab就为传递的参数,
[self test:^(int a, int b){
NSLog(@"%d",a+b);
return a + b;
}];
- (void)test:(int (^)(int, int))sumBlock
{
sumBlock(2,1);
}
4:1:block的循环引用:XMGPerson alloc init 之后在内存中产生一个对象,name 和 block是该对象的属性(因为用copy修饰,也就相当于强引用),则该对象会对这两个属性分别有一个强引用,创建完对象之后,有一个强指针p指向该对象(指针里存放的是对象的地址,变量创建之后无论是全局变量还是局部变量都会有一个强引用),__weak那部分代码是将强指针p的地址复制给一个弱指针weakSelf,此时弱指针weakSelf会有一个弱引用指向person对象,p.name = @"JACK";此时name属性会对jack有一个强引用,block会对赋值的block有一个强引用。此时不会立即调用block代码块中的任务,但是此时会检测block代码块中有无引用外部变量(即使是外部无引用,在after中引用了,也算block中引用了外部变量,此时会对访问的该对象有一个强引用或是弱引用,代码块中有引用weakP,所以会产生一个弱引用),再执行代码调用block,执行block代码块中的任务,将一个弱引用weakP指针赋值给一个强引用,此时block代码块中的strongP会对person对象有一个强引用,在执行gcd延迟函数,此时会产生延迟函数的block块,会检测延迟函数中有无引用外界的变量,有引用了strongP,则会产生一个强引用指向person对象,此时的代码块不立即执行(但是系统会有一个强指针指向该代码块,如图2),此时会执行到方法结束,强指针p销毁,弱指针weakp销毁,strongP执行完销毁,但此时block2还指向person对象,所以person对象不会销毁,能打印出name 2:像类似于GCD的延迟函数在block中,想要保住对象使其不备销毁,就在block中定义一个强引用指向就可以了

iOS开发Block的介绍以及Block的循环引用问题的更多相关文章
- iOS开发UI篇—无限轮播(循环利用)
iOS开发UI篇—无限轮播(循环利用) 一.无限轮播 1.简单说明 在开发中常需要对广告或者是一些图片进行自动的轮播,也就是所谓的无限滚动. 在开发的时候,我们通常的做法是使用一个UIScrollV ...
- iOS开发UI篇—无限轮播(循环展示)
iOS开发UI篇—无限轮播(循环展示) 一.简单说明 之前的程序还存在一个问题,那就是不能循环展示,因为plist文件中只有五个数组,因此第一个和最后一个之后就没有了,下面介绍处理这种循环展示问题的小 ...
- iOS沙盒机制介绍,Block 的介绍
一.iOS沙盒机制介绍 (转载) 1)概念:每个ios应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用放入文件 系统隔离,ios系统不允许访问 其他应用的应用沙盒,但在ios8中已经开放访 ...
- iOS开发——OC基础-ARC、BLOCK、协议
一.ARC ARC 是一种编译器特性!而不是IOS运行时特性,和JAVA中得垃圾回收机制完全不一样ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的 ...
- ios开发--GCD使用介绍:4-延迟执行操作
在开发过程中,我们有时会希望把一些操作封装起来延迟一段时间后再执行.iOS开发中,有两种常用的方法可以实现延迟执行,一种是使用GCD,另外一种是使用NSRunLoop类中提供的方法. 1.使用GCD实 ...
- [翻译] iOS开发工具的介绍(第一部分)
IOS DEVELOPMENT TIPS & TRICKS - PART I http://blog.trifork.com/2013/12/19/ios-development-tips-t ...
- ios开发杂项(基础性介绍等)
IOS Xcode开发中的文件后缀名区别m,mm,cpp,h .h :头文件.头文件包含类,类型,函数和常数的声明. .m :源代码文件.这是典型的源代码文件扩展名,可以包含Objective-C和C ...
- iOS开发-UINavigationController简单介绍
导航条或者说导航栏目现在在App中基本上也算是标配,类似于父子级别的味道在里面,UINavigationController就是负责简化这一实现功能的,属于iOS开发中比较常用的一种容器View co ...
- iOS Block详细介绍(block实现)
Block的实现 数据结构定义 block的数据结构定义如下图 对应的结构体定义如下: struct Block_descriptor { unsigned long int reserved; un ...
随机推荐
- 内存泄漏与指针悬挂&野指针介绍
内存泄漏概念:内存泄漏时指动态申请的内存空间没有正常释放,但是也不能继续使用的情况. 例如: char *ch1; ch1 = new char('A'); char = *ch2 = new cha ...
- JXNU 新生选拔赛
1001 最小的数 Problem Description 定义一种正整数集合K,集合中有N个数,集合中元素Ki(1<=i<=N)是包含i个不同质因子的最小的数.因为Ki可能会很大,所以将 ...
- Js 栈和堆的实现
一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被取出! 1.2.堆栈的基本概念 堆栈:是一种支持后进先出(LIFO)的集合,即后被插 ...
- itchat转发指定的微信群里某个用户的发言到指定的群
复读机功能, 如果有比较多的用户,超出500人,那就得分开至少两个群,如何把一些消息自动复制到另一个群呢. 自动转发指定用户的发言,转发到别的群 # !/usr/bin/env python # -* ...
- java和javascript日期校验和闰年问题分析和解决方式
1.闰年的介绍 地球绕太阳执行周期为365天5小时48分46秒(合365.24219天)即一回归年.公历的平年仅仅有365日,比回归年短约0.2422 日,所余下的时间约为四年累计一天.故四年于2月加 ...
- hbs模板(zmaze ui用的)
hbs模板(zmaze ui用的) 一.总结 1.模板引擎:就是来生成界面的啊,只不过实现了view和数据分离以及一些其它的功能(预加载等). 2.Handlebars :但他是一个单纯的模板引擎,在 ...
- Centos7安装.Net Core 2.2环境以及部署.Net Core MVC程序(Apache+Jexus环境)
原文:Centos7安装.Net Core 2.2环境以及部署.Net Core MVC程序(Apache+Jexus环境) 1.双11抢购***VPS.配置如下: CPU:2 核 内存:2048 M ...
- 【“玲珑杯”ACM比赛 Round #20 H】康娜的数学课
[链接]http://www.ifrog.cc/acm/problem/1161 [题意] 在这里写题意 [题解] 首先x<l肯定无解; 然后,肯定是要选其中的一些数字的. 而且这些数字肯定是大 ...
- 【河南省多校脸萌第六场 B】点兵点将
[链接]点击打开链接 [题意] 在这里写题意 [题解] 先每个单位都不建造bi; 打死一个ai之后,把bi加入到大根堆里面. 然后等到不够打死某个单位的时候; 从大根堆里面取出最大的那个bi;不断取, ...
- 通过wmi获取本地硬件信息的一些疑问。
通过wmi获取本地硬件信息的一些疑问. http://bbs.csdn.net/topics/391017789 http://blog.csdn.net/xcntime/article/detail ...
