博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程(二)之block小结
阅读量:4311 次
发布时间:2019-06-06

本文共 4085 字,大约阅读时间需要 13 分钟。

根据上述的博客小结如下:

Block的类型与内存管理

根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。
        NSGlobalBlock:类似函数,位于text段;
        NSStackBlock:位于栈内存,函数返回后Block将无效;
        NSMallocBlock:位于堆内存。

 无论MRC还是ARC,只要在block内部没有访问局部变量,那么这个block就存放在静态区(全局区,或者说是数据区)即NSGlobalBlock区

MRC模式下:block内部访问局部变量,这个block是存放到栈区的

ARC模式下:block内部访问局部变量,这个block是存放到堆区的

无论MRC还是ARC,局部变量copy后,这个block是存放到堆区的即NSMallocBlock

//MRC copy 使得栈区的block 拷贝到堆区,在旧版本的xcode中,strong不会拷贝到堆取,在新版本的xcode中,不管strong还是copy都在堆取,意图是让程序员少考虑内存问题,专注于业务逻辑

-(void)demo4{    //block 内修改外部变量,__block,把变量移到堆取   __block int number = 10;   NSLog(@"11 %p",&number);        //拷贝到堆取,因为生命周期比较长,不会被立即释放    void(^myBlock)() = ^{                number = 20;        NSLog(@"22 %p",&number);        NSLog(@"%d",number);          };        NSLog(@"33 %p",&number);    NSLog(@"%d---",number);        [self passBlock:myBlock];}

但对于像:

    NSMutableString *str = [NSMutableString string];

    NSMutableArray *arr = [NSMutableArray array];

    NSMutableDictionary *dic = [NSMutableDictionary dictionary];

这三类定义的局部变量我不用在前面加__block,也能在block内部改变变量的值,因为,举例:str来说,str是存放在栈区的局部变量,但是实例化的对象却是在堆区中,所以我给这个对象改变值是可以直接改变的,但像上述例子中的int对象,显然是只存在栈区的,而我在block中是相当于copy了一份在堆区,那么,显然堆区中再去访问栈区以达到改变栈区值的目的是不可行的.

 

另外:__weak的目的就是为了避免循环引用,为什么会产生循环引用呢?因为

-(void)demo1{    //定义block,内部引用self    //方法中self->block->self    //方法执行完 block->self    //并不是所有在block内部使用self就会造成循环引用的问题(retain cycle)        void(^myBlock)() = ^{        NSLog(@"%d,%@",self.number,self);    };        myBlock();    self.myblock2 = myBlock;}-(void)dealloc{    //套路:检查有没有循环引用,就查看dealloc是否被调用 //ps:循环引用不会调用这个方法,因为一直在互相引用,控制器没有被释放,没有循环引用才会调用这个方法,控制器再pop后会被释放掉.     NSLog(@"%s",__FUNCTION__);}

这个代码中注意:myBlock 中打印了self说明,myBlock引用了控制器对象self,self.myblock2 = myBlock;这行代码又用myBlock给控制器的属性赋值说明,控制器对myBlock也进行了引用,所以互相引用就造成了循环引用,因此解决循环引用就如下代码所示(加__weak):

-(void)demo2{    //写法1 self->myBlock->weakVC    __weak ViewController *weakVC = self;    //写法2    __weak typeof(self) weakSelf = self;    void(^myBlock)() = ^{        NSLog(@"%d",weakSelf.number);    };        self.myblock2 = myBlock;    }

 

 

 

 

 

 

 

 

 

 

////  ViewController.m//  blockDemo////  Created by apple on 16/8/20.//  Copyright © 2016年 itcast. All rights reserved.//#import "ViewController.h"@interface ViewController ()//MRC copy 使得栈区的block 拷贝到堆区,在旧版本的xcode中,strong不会拷贝到堆取,在新版本的xcode中,不管strong还是copy都在堆取,意图是让程序员少考虑内存问题,专注于业务逻辑@property(nonatomic,strong) void(^myblock2)();@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    [self demo1];}-(void)demo7{//MRC栈区的block 拷贝到堆区    int number = 10;    void(^myBlock)() = ^{        NSLog(@"block %d",number);    };        self.myblock2 = myBlock;     NSLog(@"%@",self.myblock2);    }-(void)demo6{    /**     ARC 会自动的把block拷贝到堆取     *  __NSMallocBlock__堆区block     MRC     __NSStackBlock__ 栈去block     */    int number = 10;    void(^myBlock)() = ^{        NSLog(@"block %d",number);    };         NSLog(@"%@",myBlock);}-(void)demo5{//block在内存中的位置    //__NSGlobalBlock__    void(^myBlock)() = ^{        NSLog(@"block");    };        NSLog(@"%@",myBlock);}-(void)demo4{    //block 内修改外部变量,__block,把变量移到堆取   __block int number = 10;   NSLog(@"11 %p",&number);        //拷贝到堆取,因为生命周期比较长,不会被立即释放    void(^myBlock)() = ^{                number = 20;        NSLog(@"22 %p",&number);        NSLog(@"%d",number);          };        NSLog(@"33 %p",&number);    NSLog(@"%d---",number);        [self passBlock:myBlock];}-(void)demo3{    //面试题:打印输出是? 10 block在声明的时候,拷贝了block内部涉及的变量,内存地址不唯一    int number = 10;    NSLog(@"11 %p",&number);        void(^myBlock)() = ^{        NSLog(@"%d",number);         NSLog(@"2 %p",&number);//        number = 20;//        NSLog(@"block %p   ",myBlock);            };        number = 20;        [self passBlock:myBlock];    }-(void)demo2{//使用block在方法间传递参数    void(^myBlock)() = ^{        NSLog(@"block");    };        [self passBlock:myBlock];}-(void)passBlock:(void(^)())block{//调用传递过来的block    block();}- (void)demo1 {    //返回值 名字 参数 与函数或者方法很像    void(^myBlock)() = ^{        NSLog(@"block");    };        NSLog(@"%@",myBlock);    //调用block    myBlock();}@end

 

转载于:https://www.cnblogs.com/yiyuanchenfeng/p/6158488.html

你可能感兴趣的文章
shell
查看>>
Sed&awk笔记之awk
查看>>
DNS泛解析配置
查看>>
Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D Bear and Two Paths
查看>>
Python学习-day1
查看>>
ORA-06512 问题解决
查看>>
hdu 2049 不容易系列之考新郎 && 对错排的详解
查看>>
10个面向程序员的在线编程网站
查看>>
c#设计模式-单例模式(面试题)
查看>>
WPF x名称空间详解
查看>>
pyenv管理多python版本
查看>>
mysql 存储过程和触发器综合例题
查看>>
深度的发现之256个class打平1个id
查看>>
0909我对编译原理的见解
查看>>
lib 和 dll
查看>>
hdu 2042 - 不容易系列之二
查看>>
Linux下设置postgresql数据库开机启动
查看>>
mysql函数技巧整理
查看>>
二叉树
查看>>
IO多路复用--epoll详解
查看>>