您的位置:首页 > 移动开发 > Objective-C

第04天实战技术(06):Block循环引用

2017-03-29 00:00 381 查看
#####一、Block循环引用

/**
循环引用 : 我引用你,你引用我,就会造成循环引用,双方都不会被销毁,导致内存泄漏
*/


presentViewController和dismissViewController的内存管理

1.当{}过后,mdVC这个对象会被销毁,但是self.presentedViewController 管理着mdVC

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
ModalViewController *mdVC = [[ModalViewController alloc]init];
[self presentViewController:mdVC animated:YES completion:nil];
NSLog(@"%@",self.presentedViewController);
}

2.当dismissViewController,mdVC就会别销毁了
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 如果控制器被dissmiss 就会被销毁
[self dismissViewControllerAnimated:YES completion:nil];
}


2.block的循环引用
A界面:ViewController
B界面:ModalViewController

2.1.当一个界面调用了自身的block,并且里面
没有使用
  弱指针的变量
__weak typeof(self) weakSelf = self;
会出现循环引用。

#import "ModalViewController.h"

@interface ModalViewController ()

@property(nonatomic) void(^block)();

@end

@implementation ModalViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];

// 弱指针 (包装 __weak typeof (self) weakSelf = self;)
// typeof(self) 相当于 ModalViewController *
// __weak typeof(self) weakSelf = self;
// block造成循环引用: Block 默认 会对里面所有强指针变量 都 强引用一次 (self)
_block = ^{
NSLog(@" -- %@",self); // 要使用弱指针 __weak typeof(self) weakSelf = self;
};
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 如果控制器被dissmiss 就会被销毁
[self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc
{
NSLog(@"%s 销毁了",__func__);
}

@end


2.2.在一个延迟执行block的注意点。我们可能在外面已经设置弱指针的对象
防止循环引用
,但是可能会在延迟
用户可能通过快速、或者是网络
出现问题: 我们获取的对象可能已经是空的了

1.如果不添加         __strong typeof(weakSelf) strongSelf = weakSelf;那么可能获取的weakSelf 是空的

#pragma 0.防止循环引用 在block内部使用 要使用弱指针对象
__weak typeof(self) weakSelf = self;
_block = ^{
// NSLog(@" -- %@",weakSelf);

#pragma 局部变量
#pragma 1.block延迟操作 要在block里面 要使用强引用指针
__strong typeof(weakSelf) strongSelf = weakSelf; // 这里使用强引用 是因为害怕用户快速点击,防止在两秒延迟拿到的 weakSelf 是空的
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@" -- %@",strongSelf);

});
};

_block();






code
ViewController

/**
循环引用 : 我引用你,你引用我,就会造成循环引用,双方都会不会被销毁,导致内存泄漏
*/

#import "ViewController.h"
#import "ModalViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
ModalViewController *mdVC = [[ModalViewController alloc]init];
// self.presentedViewController 管理着mdVC
[self presentViewController:mdVC animated:YES completion:nil];
NSLog(@"%@",self.presentedViewController);

}

@end

ModalViewController

#import "ModalViewController.h"

@interface ModalViewController ()

@property(nonatomic) void(^block)();

@end

@implementation ModalViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];

// block造成循环引用: Block 默认 会对里面所有强指针变量 都 强引用一次 (self)

// 弱指针 (包装 __weak typeof (self) weakSelf = self;)
// typeof(self) 相当于 ModalViewController *
#pragma 0.防止循环引用 在block内部使用 要使用弱指针对象
__weak typeof(self) weakSelf = self;
_block = ^{
// NSLog(@" -- %@",weakSelf);

#pragma 局部变量
#pragma 1.block延迟操作 要在block里面 要使用强引用指针
__strong typeof(weakSelf) strongSelf = weakSelf; // 这里使用强引用 是因为害怕用户快速点击,防止在两秒延迟拿到的 weakSelf 是空的
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@" -- %@",strongSelf);
//            NSLog(@" -- %@",weakSelf);

});
};

_block();
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 如果控制器被dissmiss 就会被销毁
[self dismissViewControllerAnimated:YES completion:nil];
}

- (void)dealloc
{
NSLog(@"%s 销毁了",__func__);
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息