iOS基础知识6
2017-09-07 23:59
155 查看
一、使用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需要考虑。
(出:http://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 显然这也是一个循环引用。
一个对象中强引用了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需要考虑。
(出:http://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 显然这也是一个循环引用。
相关文章推荐
- IOS基础知识记录九(Page Scroll)
- 黑马程序员——IOS基础之C语言---C语言基础知识介绍
- UIGestureRecognizer 六种手势的用法 - iOS - UI基础知识总结6
- ios蓝牙开发(一)蓝牙相关基础知识
- iOS开发多线程基础知识 NSOperation
- iOS基础知识之@property 和 Ivar 的区别
- IOS开发基础知识--碎片28
- IOS开发学习中的基础知识究竟有多重要?
- iOS基础知识
- IOS渗透测试第一步-基础知识统一放送
- iOS开发基础知识碎片
- android、IOS和手机基础知识
- IOS开发基础知识--碎片50
- iOS开发基础知识--碎片38
- IOS开发基础知识--碎片5
- IOS基础知识
- 学ios需要了解的C语言基础知识-4-进制
- iOS开发基础知识--碎片46
- IOS开发基础知识--碎片19
- IOS开发基础知识--碎片27