self.view=nil引发的思考

作者: __Mr_Xie__ | 来源:发表于2019-08-06 14:42 被阅读14次

前言

  • 场景
    2 个控制器,暂且称之为 AControllerBController。从 AController pushBController,然后再从 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 pushBController 之后,在 AControllerviewDidDisappear 中设置 AControllerself.view = nil, 然后从 BController 返回到 AController 中, AControllerviewDidLoad 又被调用了一次;如果去掉 self.view = nil,从 BController 返回到 AController 中,AControllerviewDidLoad 就不会被再次调用。

思考

self.view = nil 究竟意味什么?有以下 两点 疑问:

  • self.view = nil 时,AControllerview 被自动释放了吗?
  • self.view = nil 时,那么添加到 AControllerview 上的子控件被自动释放了吗?

通过以下代码可以验证:
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 控制器 pushBController 控制器之后,代码运行效果如下:
  • 总结
    通过上图中 中的 view 的打印出来的地址可以知道:
    self.view = nil 时,AController 控制器的 view 被释放了;
    执行 self.view = nil 操作之后,如果 view 上面相关的子控件被其他的类 强引用 的话,就不会被释放,只是引用计数减 1;如果view上面相关的子控件被其他的类 弱引用 的话,就会被释放掉。

Author

如果你有什么建议,可以关注我的公众号:iOS开发者进阶,直接留言,留言必回。

相关文章

网友评论

    本文标题:self.view=nil引发的思考

    本文链接:https://www.haomeiwen.com/subject/meipdctx.html