self.view=nil引发的思考
2019-08-06 本文已影响14人
__Mr_Xie__
前言
-
场景
有2个控制器,暂且称之为AController和BController。从AControllerpush到BController,然后再从BController返回到AController中。 -
AController 代码如下:
#import "AController.h"
#import "BController.h"
@interface AController ()
@end
@implementation AController
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"%s", __FUNCTION__);
self.view = nil;
}
- (IBAction)btnClick:(UIButton *)sender {
BController *vc = [[BController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
@end
- BController 代码如下:
#import "BController.h"
@interface BController ()
@end
@implementation BController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"BController";
self.view.backgroundColor = [UIColor brownColor];
}
@end
- 代码释义:
AController push 到 BController 之后,在 AController 的 viewDidDisappear 中设置 AController 的 self.view = nil, 然后从 BController 返回到 AController 中, AController 的 viewDidLoad 又被调用了一次;如果去掉 self.view = nil,从 BController 返回到 AController 中,AController 的 viewDidLoad 就不会被再次调用。
思考
self.view = nil 究竟意味什么?有以下 两点 疑问:
-
self.view = nil时,AController的view被自动释放了吗? -
self.view = nil时,那么添加到AController的view上的子控件被自动释放了吗?
通过以下代码可以验证:
demo地址
- AController代码如下:
#import "AController.h"
#import "BController.h"
@interface AController ()
@property (nonatomic, strong) UIView *subView;
@property (nonatomic, weak) UIView *weakView;
@end
@implementation AController
- (void)loadView {
[super loadView];
NSLog(@"%s", __FUNCTION__);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"%s", __FUNCTION__);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"%s", __FUNCTION__);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%s", __FUNCTION__);
self.title = @"self.view = nil引起的思考";
self.subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
self.subView.backgroundColor = [UIColor brownColor];
self.subView.center = self.view.center;
[self.view addSubview:self.subView];
UIView *weakView = [[UIView alloc] initWithFrame:CGRectMake(0, 300, 50, 50)];
weakView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:weakView];
self.weakView = weakView;
NSLog(@"+++++++++++++++++++ viewDidLoad 中的打印 开始++++++++++++++++++++++++");
NSLog(@"View: %@ -- %ld", self.view, CFGetRetainCount((__bridge CFTypeRef)(self.view)));
NSLog(@"subView: %@ -- %ld", self.subView, CFGetRetainCount((__bridge CFTypeRef)(self.subView)));
NSLog(@"weakView: %@", self.weakView);
NSLog(@"+++++++++++++++++++ viewDidLoad 中的打印 结束++++++++++++++++++++++++\r\n");
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"%s", __FUNCTION__);
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"%s", __FUNCTION__);
self.view = nil;
NSLog(@"+++++++++++++++++++ viewDidDisappear中设置 self.view = nil之后的打印 开始 ++++++++++++++++++++++++");
NSLog(@"View: %@ -- %ld", self.view, CFGetRetainCount((__bridge CFTypeRef)(self.view)));
NSLog(@"subView: %@ -- %ld", self.subView, CFGetRetainCount((__bridge CFTypeRef)(self.subView)));
NSLog(@"weakView: %@", self.weakView);
NSLog(@"+++++++++++++++++++ viewDidDisappear中设置 self.view = nil之后的打印 结束++++++++++++++++++++++++\r\n");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"%s", __FUNCTION__);
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) {
if (self.isViewLoaded && !self.view.window) {
self.view = nil;
}
}
}
- (IBAction)btnClick:(UIButton *)sender {
NSLog(@"+++++++++++++++++btnClick:方法中打印 开始++++++++++++++++++++++++++");
NSLog(@"View: %@ -- %ld", self.view, CFGetRetainCount((__bridge CFTypeRef)(self.view)));
NSLog(@"subView: %@ -- %ld", self.subView, CFGetRetainCount((__bridge CFTypeRef)(self.subView)));
NSLog(@"weakView: %@", self.weakView);
NSLog(@"+++++++++++++++++btnClick:方法中打印 结束++++++++++++++++++++++++++\r\n");
BController *vc = [[BController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
@end
- BController代码
#import "BController.h"
@interface BController ()
@end
@implementation BController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"BController";
self.view.backgroundColor = [UIColor brownColor];
}
@end
-
打印结果
从AController控制器push到BController控制器之后,代码运行效果如下:
-
总结
通过上图中①和②中的view的打印出来的地址可以知道:
self.view = nil时,AController控制器的view被释放了;
执行self.view = nil操作之后,如果view上面相关的子控件被其他的类强引用的话,就不会被释放,只是引用计数减1;如果view上面相关的子控件被其他的类弱引用的话,就会被释放掉。
Author
如果你有什么建议,可以关注我的公众号:iOS开发者进阶,直接留言,留言必回。