一个和viewcontroller生命周期相关的bug

一个和viewController生命周期相关的bug

最近在项目的开发过程中,遇到一个隐藏的关于viewController生命周期相关的bug,我已经写了一个demo把这个问题复现,可以点击demo查看。

问题复现:

1.创建一个controller,给controller,添加两个属性

@interface LoadViewController : UIViewController
@property (nonatomic, strong) UIView *centerView;
@property (nonatomic, strong) NSString *testString;
@end

在controller的实现文件中,写以下几个方法

- (void)loadView {

    [super loadView];

}

- (void)viewDidLoad {

    [super viewDidLoad];
    [self.view addSubview:self.centerView];
    NSLog(@"f == %p",self.centerView);
    self.view.backgroundColor = [UIColor whiteColor];

}

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    NSLog(@"t == %p",self.centerView);
    NSLog(@"subviews == %@",self.view.subviews);
    UIView *temp = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 10, 10)];
    temp.backgroundColor = [UIColor orangeColor];
    [self.centerView addSubview:temp];

}

#pragma mark - Setter

- (void)setTestString:(NSString *)testString {

    _testString = testString;
    self.centerView.frame = CGRectMake(0, 0, 20, 20);
    NSLog(@"s == %p",self.centerView);

}

#pragma mark - Getter 

- (UIView *)centerView {

    if (nil == _centerView) {
        _centerView = [[UIView alloc]initWithFrame:CGRectMake(0, 150, self.view.bounds.size.width, 50)];
        _centerView.backgroundColor = [UIColor grayColor];
    }
    return _centerView;

}

在viewDidLoad方法中,把centerView添加到self.view上,然后在viewWillAppear中在centerView上添加一个橙色的小块,在testString的set方法中,把centerView的大小改为宽高20,controller的创建如下:

 LoadViewController *ctl = [[LoadViewController alloc]init];
ctl.testString = @"test";
[self.navigationController pushViewController:ctl animated:YES];

运行之后发现centerview的大小并没有改变为宽高20,那个橙色的小色块也并没有添加到centerview中,那么是哪里出了问题呢?
在不同的地方打印如下:

2016-04-01 09:52:44.588 LoadViewDemo[55368:6620177] f == 0x7ffaf2c264e0
2016-04-01 09:52:44.588 LoadViewDemo[55368:6620177] s == 0x7ffaf2c29900
2016-04-01 09:52:44.590 LoadViewDemo[55368:6620177] t == 0x7ffaf2c29900
2016-04-01 09:52:44.590 LoadViewDemo[55368:6620177] subviews == (
    "<UIView: 0x7ffaf2c264e0; frame = (0 150; 375 50); layer = <CALayer: 0x7ffaf2c16da0>>"
)

我们发现,centerview在不同的时期,有两个不相同的地址,属性self.centerView的地址为0x7ffaf2c29900 而添加到self.view的centerview的内存地址为0x7ffaf2c264e0,为什么会出现这种情况呢,短短几行代码,竟然出现了两个centerview 。通过断点调试发现,第一次centerview创建时,在执行完 centerView = [[UIView alloc]initWithFrame:CGRectMake(0, 150, self.view.bounds.size.width, 50)] 这一行时,然后调转到了去执行viewDidLoad,然后接着回来执行了 centerView.backgroundColor = [UIColor grayColor] 这一行,然后竟然又执行了 _centerView = [[UIView alloc]initWithFrame:CGRectMake(0, 150, self.view.bounds.size.width, 50)] 这一行 ,仔细观察这行代码,发现只有self.view.bounds.size.width可能不正常,把它换掉,果然问题不再出现。
问题找到了,要了解问题为什么出现,我们需要好好看一下self.view.bounds.size.width这个代码,到底做了什么。

问题原因:

当调用ctl.testString = @”test”时,会self.centerView.frame = CGRectMake(0, 150, 50, 100),此时会去调用

- (UIView *)centerView {

    if (nil == _centerView) {
        _centerView = [[UIView alloc]initWithFrame:CGRectMake(0, 150, self.view.bounds.size.width, 50)];
        _centerView.backgroundColor = [UIColor grayColor];
    }
    return _centerView;

}

来创建centerview,这时self.view是空的,当调用self.view并且self.view为空时,会调用loadView方法,之后会调用viewDidLoad方法,而在viewDidLoad方法中,我们又再次调用了上面的创建cenerview的get方法,由于此时上一次创建并没有完成,所以此时会再次重新创建一个。真相大白

TipS

现在我们来看一下loadView的释义
The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.
当使用self.view且self.view为空时,就会触发loadView方法。
viewDidLoad的释义
this method is called after the view controller has loaded its view hierarchy into memory
当loadView调用完成后,变会调用viewDidLoad
原来如此

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值