block介绍内存管理修饰

block块存储位置

block块根据情况有两种可能的存储位置,一种存在代码区,一种存在堆区。

1、如果block块没有访问处于栈区的变量(比如局部变量),也没有访问堆区的变量(比如我们alloc创建的对象),那就存在代码区,即使访问了全局变量,也依然存在代码区。

2、如果访问了栈区或者堆区的变量,那就会被存在堆区(实际存在栈区,ARC下会自动拷贝到堆区)。

关于存在堆区的情况,有一点需要注意的是,堆区是不断变化的,不断地有变量的创建和销毁,如果block块没有强引用,那也随时可能被销毁,这就导致一旦在销毁时访问block块,程序就会崩溃,所以,在定义block时,内存修饰最好用strong或者copy。而且在使用时也最好先判断一下block是否为空,比如:

if(!block){

return;

}block();

1

2

3

4

循环引用

既然在修饰block时,使用了strong,那么另一个问题就需要注意了,也就是循环引用。

当使用了strong修饰后,self会强引用block,而如果在block中又需要访问self的一些属性或者方法,从而调用了self,这时self和block就进入循环引用,容易内存溢出。

解决的办法时在block中的需要用到self时,事先将self用__weak修饰,这样互相引用的一方就不再是强引用了。

比如:

__weak ViewController *weakSelf =self;self.block = ^{    weakSelf.str= @"123";};

1

2

3

4

但是这样还不够,在多线程下,单单使用weakSelf,可能前一刻weakSelf还在,后面需要用时却被释放掉了,毕竟弱引用是不稳定的,这时候就需要又使用一个修饰符__strong来在block中修饰,是不是操碎了心。

因此更好的释放方式如下:

__weak__typeof(self) *weakSelf =self;self.block= ^{    __strong__typeof(self) strongSelf = weakSelf;if(strongSelf) {        strongSelf.str= @"123";    }// 如果不用了,应置为空strongSelf.block=nil;};

1

2

3

4

5

6

7

8

9

平常使用block的情况很多,很多人往往都是直接拿样例代码改着用了,不知道为什么要这么修饰block,也不知道weakSelf、strongSelf有什么用。这里就从存储位置来解释为什么要这样修饰block,从而又会造成循环引用的问题,最后如何去解决他。希望可以帮助大家更好的理解手中的每一行代码。

block块根据情况有两种可能的存储位置,一种存在代码区,一种存在堆区。

1、如果block块没有访问处于栈区的变量(比如局部变量),也没有访问堆区的变量(比如我们alloc创建的对象),那就存在代码区,即使访问了全局变量,也依然存在代码区。

2、如果访问了栈区或者堆区的变量,那就会被存在堆区(实际存在栈区,ARC下会自动拷贝到堆区)。

关于存在堆区的情况,有一点需要注意的是,堆区是不断变化的,不断地有变量的创建和销毁,如果block块没有强引用,那也随时可能被销毁,这就导致一旦在销毁时访问block块,程序就会崩溃,所以,在定义block时,内存修饰最好用strong或者copy。而且在使用时也最好先判断一下block是否为空,比如:

if(!block){

return;

}block();

1

2

3

4

循环引用

既然在修饰block时,使用了strong,那么另一个问题就需要注意了,也就是循环引用。

当使用了strong修饰后,self会强引用block,而如果在block中又需要访问self的一些属性或者方法,从而调用了self,这时self和block就进入循环引用,容易内存溢出。

解决的办法时在block中的需要用到self时,事先将self用__weak修饰,这样互相引用的一方就不再是强引用了。

比如:

__weak ViewController *weakSelf =self;self.block = ^{    weakSelf.str= @"123";};

1

2

3

4

但是这样还不够,在多线程下,单单使用weakSelf,可能前一刻weakSelf还在,后面需要用时却被释放掉了,毕竟弱引用是不稳定的,这时候就需要又使用一个修饰符__strong来在block中修饰,是不是操碎了心。

因此更好的释放方式如下:

__weak__typeof(self) *weakSelf =self;self.block= ^{    __strong__typeof(self) strongSelf = weakSelf;if(strongSelf) {        strongSelf.str= @"123";    }// 如果不用了,应置为空strongSelf.block=nil;};

1

2

3

4

5

6

7

8

9

平常使用block的情况很多,很多人往往都是直接拿样例代码改着用了,不知道为什么要这么修饰block,也不知道weakSelf、strongSelf有什么用。这里就从存储位置来解释为什么要这样修饰block,从而又会造成循环引用的问题,最后如何去解决他。希望可以帮助大家更好的理解手中的每一行代码。

你可能感兴趣的:(block介绍内存管理修饰)