self.view=nil引发的思考
2019-08-06 本文已影响14人
__Mr_Xie__
前言
-
场景
有2
个控制器,暂且称之为AController
和BController
。从AController
push
到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开发者进阶
,直接留言,留言必回。
