iOS基础知识6

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

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

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

1id __weak weakSelf = self;或者__weak __typeof(self) weakSelf = self

2id __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(如UIViewblock版本写动画时),是否也考虑引用循环问题?

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


所谓引用循环是指双向的强引用,所以那些单向的强引用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,如GCDNSNotificationCenter就要小心一点:比如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 显然这也是一个循环引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值