欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS编程开发教程_iOS基础知识6

程序员文章站 2022-05-16 10:01:54
ios开发教程_ios基础知识6。 一、使用block时什么情况会发生循环引用,如何解决? 一个对象中强引用了block,在block中又强引用了该对象,就会发生循环引用。 解决方法是将该对象使用_...

ios开发教程_ios基础知识6。

一、使用block时什么情况会发生循环引用,如何解决?

一个对象中强引用了block,在block中又强引用了该对象,就会发生循环引用。

解决方法是将该对象使用__weak或者__block修饰符修饰之后再在block中使用。

1、id __weak weakself = self;或者__weak __typeof(self) weakself = self;

2、id __block weakself = self;

检测代码中是否存在循环引用问题,可使用facebook开源的一个检测工具fbretaincycledetector

二、在block内如何修改block外部变量?

1、可以修改成static全局变量。

2、可以修改用新关键字 __block修饰的变量。

__block int variable = 0;

void (^foo)(void) = ^{

variable = 9;

};

foo(); //这里variable的值被修改为9

variable在定义前是栈区,但只要进入了block区域,就变成了堆区。这才是__block关键字的真正作用。block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。栈区是红灯区,堆区才是绿灯区。

三、使用的某些block api(如uiview的block版本写动画时),是否也考虑引用循环问题?

系统的某些block api中,如uiview的block版本写动画时不需要考虑,但也有一些api 需要考虑。

(出:https://www.jianshu.com/p/0d145fc72d3d)

所谓“引用循环”是指双向的强引用,所以那些“单向的强引用”(block强引用self)没有问题,比如这些:

[uiviewanimatewithduration:durationanimations:^{ [self.superviewlayoutifneeded]; }];

[[nsoperationqueuemainqueue] addoperationwithblock:^{ self.someproperty= xyz; }];

[[nsnotificationcenterdefaultcenter] addobserverforname:@"somenotification"object:nilqueue:[nsoperationqueuemainqueue]usingblock:^(nsnotification* notification) { self.someproperty= xyz; }];

这些情况不需要考虑“引用循环”。

但如果你使用一些参数中可能含有ivar的系统api,如gcd、nsnotificationcenter就要小心一点:比如gcd内部如果引用了self,而且gcd的其他参数是ivar,则要考虑到循环引用:

__weak__typeof__(self) weakself = self;dispatch_group_async(_operationsgroup, _operationsqueue, ^{__typeof__(self) strongself = weakself;[strongselfdosomething];[strongselfdosomethingelse];} );

__weak__typeof__(self) weakself = self; _observer = [[nsnotificationcenterdefaultcenter]addobserverforname:@"testkey"object:nilqueue:nilusingblock:^(nsnotification*note) {__typeof__(self) strongself = weakself; [strongselfdismissmodalviewcontrolleranimated:yes]; }];

self --> _observer --> block --> self 显然这也是一个循环引用。