关于OC中的Block使用以及ARC和MAR下的内存管理方式
来源:互联网 发布:数据库事务详解 编辑:程序博客网 时间:2024/06/05 18:51
1.什么是Block?
Block是属于C语言框架
Block是一种数据类型(类似int)
Block是一段代码块,只有在被调用的时候被执行(类似函数和方法)
Block可以定义成临时变量
Block可以定义成参数
Block可以定义成属性
2.Block的语法结构
1.无参数,无返回值
/*
数据类型 : void(^)()
变量名 : task1
值 : ^{ NSLog(@"task1"); };
*/
void(^task1)() = ^{
NSLog(@"task1");
};
2.有参数,无返回值
// 参数类型(如果有形参,这个可省) 形参
void(^task2)(NSString *) = ^(NSString *str){
NSLog(@"task2 %@",str);
};
3.无参数,有返回值
int(^task3)() = ^{
return 1;
};
4.有参数,有返回值
int(^task4)() = ^(int a,int b){
return a + b;
};
3.ARC下,Block的内存空间
结论:
1.ARC环境下,单纯的定义一个block存储在全局区 <__NSGlobalBlock__: 0x1045c60b0>
示例代码
- (void)blockDemo
{
void(^task1)() = ^{
NSLog(@"task");
};
task1();
// block的本质是指针对象
// ARC环境下,单纯的定义一个block存储在全局/常量区 <__NSGlobalBlock__: 0x10e80f100>
NSLog(@"task1==%@",task1);
}
控制台打印:
2016-06-27 08:55:51.263 Block使用[732:22600] task
2016-06-27 08:55:51.264 Block使用[732:22600] task1==<__NSGlobalBlock__: 0x10e80f100>
4.ARC下,Block内访问外部变量的内存变化
结论:
前提是ARC : Block访问外部的变量
2.ARC环境下,block访问外部的变量时存储在堆区 <__NSMallocBlock__: 0x7fa8fd00c1b0>
2.1 在block访问这个变量之前,变量在栈区 == 0x7fff53c73bfc
2.2 在block内部访问这个变量时,变量会被block拷贝到堆区 0x7fe851517880
示例代码:
#pragma mark - ARC - Block访问外部的变量
// 需求 : 研究block和外部变量的内存的变化
- (void)blockDemo1
{
int num = 10;
// 在block访问这个变量之前,变量在栈区 == 0x7fff52544bec
NSLog(@"num01==%p",&num);
void(^task1)() = ^{
// 在block内部访问这个变量时,变量会被block拷贝到堆区 0x7f8108e0d620
NSLog(@"task1 %d %p",num,&num);
};
task1();
// block的本质是指针对象
// ARC环境下,block访问外部的变量时存储在堆区 <__NSMallocBlock__: 0x7f8108e0d600>
NSLog(@"task1==%@",task1);
// 当block在其内部使用完了外部的变量之后,这个变量又会重新回到栈区 0x7fff52544bec
NSLog(@"num02==%p",&num);
}
控制台打印日志:
2016-06-27 08:59:39.334 Block使用[753:25411] num01==0x7fff52544bec
2016-06-27 08:59:39.334 Block使用[753:25411] task1 10 0x7f8108e0d620
2016-06-27 08:59:39.334 Block使用[753:25411] task1==<__NSMallocBlock__: 0x7f8108e0d600>
2016-06-27 08:59:39.334 Block使用[753:25411] num02==0x7fff52544bec
5.ARC下,Block内修改外部变量的内存变化
结论:
前提是ARC : Block修改外部的变量
1.ARC环境下,当block修改外部变量的时候,会在堆区 <__NSMallocBlock__: 0x7f82ac8a6130>
2.在block的外面,即使你使用__block修饰了,那么他的地址依然不变,在栈区 0x7fff5e101bf8
3.在block内部修改外部的变量时,使用__block修饰了外部的变量之后,外部的变量会在堆区0x7f9d10e0bcc8
示例代码
#pragma mark - ARC - Block修改外部的变量
// 需求 : 研究block和外部变量的内存的变化
- (void)blockDemo2
{
__block int num = 10;
// 在block的外面,即使你使用__block修饰了,那么他的地址依然不变,在栈区 0x7fff57337be8
NSLog(@"num01==%p",&num);
void(^task2)() = ^{
/*
提示 : 在block内部修改外部变量是不被允许的
如果非要修改,那么久需要把外部的变量用 __block 来修饰
*/
num = 20;
// 在block内部修改外部的变量时,使用__block修饰了外部的变量之后,外部的变量会在堆区 0x7fd3ea443ad8
NSLog(@"task2 %d =%p",num,&num);
};
task2();
// 当block修改外部变量的时候,会在堆区 <__NSMallocBlock__: 0x7fd3ea438d70>
NSLog(@"task2%@",task2);
// 当block内部修改完外部的变量之后,那么这个变量的就会保存到堆区 0x7fd3ea443ad8
NSLog(@"num02==%p",&num);
}
控制台打印日志
2016-06-27 09:04:17.459 Block使用[773:28467] num01==0x7fff57337be8
2016-06-27 09:04:17.460 Block使用[773:28467] task2 20 =0x7fd3ea443ad8
2016-06-27 09:04:17.460 Block使用[773:28467] task2<__NSMallocBlock__: 0x7fd3ea438d70>
2016-06-27 09:04:17.460 Block使用[773:28467] num02==0x7fd3ea443ad8
6.MRC下,Block的内存位置
结论:
1.MRC环境下,单纯的定义一个block存储在全局区 <__NSGlobalBlock__: 0x1045c60b0>
示例代码
- (void)blockDemo1
{
void(^task1)() = ^{
};
task1();
// 全局/常量区 <__NSGlobalBlock__: 0x10ddf10f0>
NSLog(@"%@",task1);
}
控制台信息
2016-06-27 09:42:17.813 MRC下Block内存管理[973:45271] <__NSGlobalBlock__: 0x10ddf10f0>
7.MRC下,Block的访问外部变量的内存变化
结论:
1.MRC环境下,Block访问外部变量的时候存放在栈区。 <__NSStackBlock__: 0x7fff58e23b08>
a.Block访问外部变量时,外部变量在栈区,地址 0x7fff58e23b3c
b.Block访问外部变量时,外部变量依然在栈区,但是地址发生了变化 0x7fff58e23b28
c.Block访问结束以后。外部变量依然在栈区,并且地址和原始的一致。
示例代码
- (void)blockDemo2
{
int num = 10;
// 变量的内存在栈区 0x7fff58e23b3c
NSLog(@"num01==%p",&num);
void(^task2)() = ^{
// 外部的变量在block内部依然在栈区,但是地址变了 0x7fff58e23b28 (地址变化了,内存空间没变)
NSLog(@"task2 %d %p",num,&num);
};
task2();
// block存储在栈区 <__NSStackBlock__: 0x7fff58e23b08>
NSLog(@"%@",task2);
// 变量依然在栈区,并且地址和开始时的一样 0x7fff58e23b3c
NSLog(@"num02==%p",&num);
}
控制台信息
2016-06-27 09:47:52.118 MRC下Block内存管理[987:48208] num01==0x7fff58e23b3c
2016-06-27 09:47:52.119 MRC下Block内存管理[987:48208] task2 10 0x7fff58e23b28
2016-06-27 09:47:52.119 MRC下Block内存管理[987:48208] <__NSStackBlock__: 0x7fff58e23b08>
2016-06-27 09:47:52.119 MRC下Block内存管理[987:48208] num02==0x7fff58e23b3c
8.MRC下,Block修改外部变量的内存变化
结论:
1.MRC环境下,Block修改外部变量时存放在栈区<__NSStackBlock__: 0x7fff57e2cae0>
a.Block修改外部变量前,外部变量存放在栈区
b.Block修改外部变量时,外部变量依然存放在栈区,但是地址发生了变化。
c.Block修改外部变量之后,外部变量的地址已经发生变化,已经不是原始值了。
示例代码
- (void)blockDemo3
{
__block int num = 10;
// 在block访问之前,外部变量存放在栈区 0x7fff57e2cb38
NSLog(@"num01==%p",&num);
void (^task3)() = ^{
num = 20;
//在block修改时,外部变量依然存放在栈区,但是地址发生了变化, 0x7fff57e2cb38
NSLog(@"task3 %d %p",num,&num);
};
task3();
// block的地址存放在栈区 <__NSStackBlock__: 0x7fff57e2cae0>
NSLog(@"%@",task3);
// 外部变量在block内部修改以后,地址为修改时的地址,依然存放在栈区 0x7fff57e2cb38
NSLog(@"num02==%p",&num);
}
控制台信息
2016-06-27 10:00:01.069 MRC下Block内存管理[1006:53704] num01==0x7fff57e2cb38
2016-06-27 10:00:01.069 MRC下Block内存管理[1006:53704] task3 20 0x7fff57e2cb38
2016-06-27 10:00:01.069 MRC下Block内存管理[1006:53704] <__NSStackBlock__: 0x7fff57e2cae0>
2016-06-27 10:00:01.070 MRC下Block内存管理[1006:53704] num02==0x7fff57e2cb38
8.为什么Block属性需要使用copy修饰
a.在ARC下,使用strong和copy都是一样的,因为在访问/修改外部变量的时候,block都是在堆区,苹果官方建议使用copy
b.在MRC下,单纯的Block是存放在全局/常量区的,如果Block访问/修改外部变量后,block存放在了栈区,在栈区是不可以全局共享的,只有堆区的对象,变量才会被全局共享,所以使用copy拷贝一份Block到堆区中,这样Block才会全局共享。
- 关于OC中的Block使用以及ARC和MAR下的内存管理方式
- 关于OC中的Block使用以及ARC和MAR下的内存管理方式
- 关于OC中在ARC和MAR下的内存管理方式
- OC的内存管理方式----MRC & ARC
- 黑马程序员 OC中的内存管理及MRC和ARC单个对象的内存管理问题
- OC-049.集合中的内存管理(MRC和ARC)
- ARC的使用以及内存管理
- ios开发 block 在ARC机制下的内存管理
- block的理解与 MRC,ARC下内存管理
- ARC和非ARC下使用Block属性的问题
- ARC和非ARC下使用Block属性的问题
- ARC和MRC下的block的内存分布详解
- oc的ARC的内存管理
- IOS开发---OC语言-㉙内存管理:block的使用
- 黑马程序员-11.OC的内存管理和block、protocol
- iOS中的ARC---内存管理的思考方式
- OC语法<2.3>内存管理:ARC机制下的内存管理
- iOS ARC下的内存管理问题以及解决办法
- mysql 5.6 timestamp变化--explicit_default_for_timestamp
- PO BO VO DTO POJO DAO概念及其作用(附转换图)
- [Android]自动格式化识别银行卡的EditText
- html5多媒体格式支持
- 工作之一
- 关于OC中的Block使用以及ARC和MAR下的内存管理方式
- Android中onInterceptTouchEvent与onTouchEvent(图文)
- Class类的常见方法示例,记不住,先保存下
- C++——queue
- Asp.net Mvc 数据验证
- 集合详解(二)----ArrayList源代码剖析(JDK1.7)
- java I/O流——File类的基本用法
- X++ to CIL
- 内网服务器无外网上网 &&端口映射