首先来看一个动态图:
由图可知,我们从One跳转到了Two(TwoViewController)
接下来看一段代码:
//
// JLPerson.h
// BlockTest
//
// Created by Mac on 15-3-28.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import
typedef void (^MyBlock)();
@interface JLPerson : NSObject
@property (nonatomic, copy)NSString *name;
@property (nonatomic, copy)MyBlock block;
@end
//
// JLPerson.m
// BlockTest
//
// Created by Mac on 15-3-28.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLPerson.h"
@implementation JLPerson
@end
//
// JLTwoViewController.m
// BlockTest
//
// Created by Mac on 15-3-28.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLTwoViewController.h"
#import "JLPerson.h"
@interface JLTwoViewController ()
@property (nonatomic, strong)NSArray *persons;
@property (nonatomic, copy)NSString *title;
@end
@implementation JLTwoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self testBlock];
}
- (void)testBlock{
JLPerson *person1 = [[JLPerson alloc] init];
person1.name = @"zhangsan";
JLPerson *person2 = [[JLPerson alloc] init];
person2.name = @"lisi";
person2.block = ^{
self.title = @"Hello World";
};
self.persons = @[person1, person2];
}
- (void)dealloc{
NSLog(@"---JLTwoViewController---");
}
@end
从代码中我们可以看到:
1,JLPerson有一个结构体MyBlock类型的属性
2,JLTwoViewController中有一个数组persons,该数组用于存储JLPerson对象
3,persons数组中有一个name属性为"lisi"的JLPerson对象
4,在JLTwoViewController中重写了父类的dealloc方法,该方法用于查看JLTwoViewController是否被销毁。
当我们执行上述代码时,会来到动态图所示的One,然后点击“跳转到Two”,然后点击“返回One”。
正常情况下,当点击“返回One”回到One之后,这时应该会调用JLTwoViewController的dealloc方法,打印出log,其实不然。
JLTwoViewController中有一个强引用(strong)的persons指向了NSArray,NSArray中有一个强引用的“lisi”指向了JLPerson,JLPerson中有一个强引用(copy也是强引用)的block,该block中self指向了JLTwoViewController。于是形成了循环引用,这些对象都不会被释放,导致了内存泄露。也就是说,当我们点击“返回One”,JLTwoViewController并不会被销毁。
解决办法:
//
// JLTwoViewController.m
// BlockTest
//
// Created by Mac on 15-3-28.
// Copyright (c) 2015年 vxinyou. All rights reserved.
//
#import "JLTwoViewController.h"
#import "JLPerson.h"
@interface JLTwoViewController ()
@property (nonatomic, strong)NSArray *persons;
@property (nonatomic, copy)NSString *title;
@end
@implementation JLTwoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self testBlock];
}
- (void)testBlock{
// 第一种写法
// __unsafe_unretained JLTwoViewController *selfVC = self;
// 第二种写法
// __unsafe_unretained typeof(self) selfVC = self;
// 第三种写法
// __weak JLTwoViewController *selfVC = self;
// 第四种写法
__weak typeof(self) selfVC = self;
// 以上四种写法都可以
JLPerson *person1 = [[JLPerson alloc] init];
person1.name = @"zhangsan";
JLPerson *person2 = [[JLPerson alloc] init];
person2.name = @"lisi";
person2.block = ^{
selfVC.title = @"Hello World";
};
self.persons = @[person1, person2];
}
- (void)dealloc{
NSLog(@"---JLTwoViewController---");
}
@end
从代码中可以看到,我们强制的使用了弱引用,也就是让上图所示的第④条线变成了弱引用,这样就打破这个循环引用,JLTwoViewController就能够正常销毁。