IOS viewDidLoad方法被执行两次(viewDidLoad和loadView方法详解)

为了搞清楚viewDidLoad、loadView等方法的用途和调用顺序,写了一个小demo,不料viewDidLoad方法被执行了两次,模拟器也一直是黑屏。查看了这两个方法的官方解释后找到了错误原因和解决方法。

首先来看UIViewController.h文件中对viewDidLoad方法的解释:

- (void)viewDidLoad; 
// Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

接下来是对loadView方法的解释:

- (void)loadView; 
// This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

无论是从xib文件中加载视图,还是自己创建视图,viewDidLoad方法都会被调用,而且都是在视图已经被加载后调用,所以这里可以明确的一点是,任何UI控件的创建都不应该在viewDidLoad方法中被实现,因为这是xib文件或者loadView方法的任务。viewDidLoad只是通过nib或者loadView方法加载视图的一周拓展和补充机制,比如一些不方便通过nib设置的属性或是临时需要进行处理的控件内容。

至于loadView方法和xib文件的关系,个人的理解是:真正的UI控件的创建,都是要通过调用loadView中的代码来实现的,只不过在xib文件中,这些代码以xml格式的文档被保存,并且苹果通过storyboard解析这个xml文档,形成了一个可视化的图形界面。这是两者的共同点,至于不同点,官方文档中的解释已经很清楚了,一旦调用了loadView方法就意味着不是用nib文件。这就意味着loadView和xib文件不兼容。loadView具有更高的优先级。

下面通过几个实验来证明以上观点。
实验1:
创建一个空的工程文件,在viewDidLoad函数中写入简单的一行代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"123");
}

实验结果:运行程序后发现:控制台输出一行结果“123”。模拟器显示一个纯白色的界面。
实验分析:控制台的结果非常容易理解。但是我们并没有创建一个UIView或者设置它的背景颜色,系统是怎么创建我们在模拟器中看到的内容的呢?
答案是,如果我们不实现loadView方法,系统会默认我们不适用自定义的方式创建view而是从nib文件中加载。这时候就回去storyboard或者其他相应的nib文件中去寻找加载视图的代码。由于默认的ViewController类在main.storyboard中有自己的nib文件,所以可以成功的加载一个UIView。

实验2:
实现一个空的loadView方法:

- (void)loadView{
}

实验结果:运行程序后发现,控制台输出两行“123”,模拟器黑屏。
实验分析:模拟器黑屏非常容易理解,因为我们实现了loadView方法,编译器以为我们要自定义一个UIView对象,从而去执行loadView方法中的代码,试图创建一个UIView,但是显然这样做会失败,所以得到一个黑色的(没有任何内容)的界面。至于为什么viewDidLoad方法会被调用两次,原因并不清楚(希望读到此处的大牛留言指教)。

实验三:
实现完整的loadView方法:

- (void)loadView{
    self.view = [[ UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.view.backgroundColor = [UIColor whiteColor];
}

实验结果:同实验1的结果
实验分析:实现了一个完整的UIView的创建过程,与通过nib文件创建非常类似。

通过以上几个实验得出以下结论:
1.如果想要通过自定义的代码创建UIView,把这些代码都写入loadView方法里面去。
2.希望通过nib文件创建UIView的话,不要重写loadView方法。
3.viewDidLoad方法被执行两次很有可能是重写了一个不完整的loadView方法导致的 。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 iOS 睡眠解析加速度和陀螺仪代码的示例: ```swift import CoreMotion class SleepAnalysisViewController: UIViewController { let motionManager = CMMotionManager() override func viewDidLoad() { super.viewDidLoad() startAccelerometerUpdates() startGyroUpdates() } func startAccelerometerUpdates() { motionManager.accelerometerUpdateInterval = 1.0 / 60.0 motionManager.startAccelerometerUpdates(to: .main) { (accelerometerData, error) in guard let data = accelerometerData else { return } // 处理加速度数据 } } func startGyroUpdates() { motionManager.gyroUpdateInterval = 1.0 / 60.0 motionManager.startGyroUpdates(to: .main) { (gyroData, error) in guard let data = gyroData else { return } // 处理陀螺仪数据 } } } ``` 这段代码中,我们使用了 CoreMotion 框架来获取设备的加速度和陀螺仪数据。首先,我们创建了一个 `CMMotionManager` 实例,然后在 `viewDidLoad` 中用了 `startAccelerometerUpdates()` 和 `startGyroUpdates()` 方法来开始获取加速度和陀螺仪数据。 在 `startAccelerometerUpdates()` 方法中,我们设置了加速度数据的更新间隔,并用了 `startAccelerometerUpdates(to:withHandler:)` 方法来开始获取加速度数据。在闭包中,我们检查了数据是否可用,如果可用则进行处理。 在 `startGyroUpdates()` 方法中,我们也设置了陀螺仪数据的更新间隔,并用了 `startGyroUpdates(to:withHandler:)` 方法来开始获取陀螺仪数据。在闭包中,我们同样检查了数据是否可用,如果可用则进行处理。 需要注意的是,获取加速度和陀螺仪数据需要消耗大量的设备资源,因此我们需要在适当的时候停止数据的获取,以避免影响设备性能和电池寿命。可以在 `viewWillDisappear` 中用 `stopAccelerometerUpdates()` 和 `stopGyroUpdates()` 方法来停止数据的获取。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值