viewdidLoad viewillappear

本文详细解析了iOS视图控制器的生命周期方法,包括init、viewDidLoad等关键方法的作用及调用时机,帮助开发者理解如何正确地进行视图管理和内存优化。

iOS视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear的区别及用途

init-初始化程序

viewDidLoad-加载视图

viewWillAppear-UIViewController对象的视图即将加入窗口时调用;

viewDidApper-UIViewController对象的视图已经加入到窗口时调用;

viewWillDisappear-UIViewController对象的视图即将消失、被覆盖或是隐藏时调用;

viewDidDisappear-UIViewController对象的视图已经消失、被覆盖或是隐藏时调用;

viewVillUnload-当内存过低时,需要释放一些不需要使用的视图时,即将释放时调用;

viewDidUnload-当内存过低,释放一些不需要的视图时调用。

  

        视图控制对象通过alloc和init来创建,但是视图控制对象不会在创建的那一刻就马上创建相应的视图,而是等到需要使用的时候才通过调用loadView来创建,这样的做法能提高内存的使用率。比如,当某个标签有很多UIViewController对象,那么对于任何一个UIViewController对象的视图,只有相应的标签被选中时才会被创建出来。

比如如下代码:

[plain]  view plain copy
  1. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  2. {  
  3.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  4.     if (self) {  
  5.         // Custom initialization  
  6.         UITabBarItem *tbi = [self tabBarItem];  
  7.         [tbi setTitle:@"CurrentTime"];  
  8.         [[self view ] setBackgroundColor:[UIColor yellowColor]];  
  9.         }  
  10.     return self;  
  11. }  

我们将UIViewController的init方法中访问的实例变量view在init中将背景设置为黄色,运行程序,我们能发现背景的确变成了黄色,但是,在我们还没有需要使用视图的时候,该视图已经加载好了,在UIViewController的初始方法中访问实例变量view,会导致延迟载入机制失效,这个问题看上去不是很严重,但是如果考虑到内存过低警告,那么问题就大了。。。

  

运行程序,选择模拟器中的硬件->模拟内存过低警告,我们会发现,原本设置的黄色背景不见了,这是因为,内存过低,视图控制对象会在发出内存过低警告时收到didReceiveMemoryWarning消息,该方法默认实现,检查视图控制对象的视图是否可见,如果不可见,则释放掉,下次在加载该视图时就不会执行init方法,而是只执行viewDidLoad方法,所以需要将[[selfview ] setBackgroundColor:[UIColoryellowColor]];放到viewDidLoad中,这样如果视图因为内存过低被释放掉了,下次需要使用到该视图的时候,程序会默认取执行该视图的viewDidLoad方法,这样背景颜色就又出来了。

 

init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear的执行顺序:

 从程序的log来看:

2012-10-19 15:51:44.811inHyron[483:b903] init

2012-10-19 15:51:54.081inHyron[483:b903] viewDidLoad

2012-10-19 15:51:54.082inHyron[483:b903] viewVillAppear

2012-10-19 15:51:54.084 inHyron[483:b903] viewDidAppear

很明显,先执行init、然后执行viewDidLoad,然后是viewWillAppear最后是viewDidAppear,这样视图就创建好了,当视图消失或者被覆盖的时候:

2012-10-19 15:54:14.557inHyron[483:b903] viewWillDisappear

2012-10-19 15:54:14.558inHyron[483:b903] viewDidDisappear

这样一来视图就消失了,当模拟内存警告的时候:

2012-10-19 15:55:14.333inHyron[483:b903] Received simulated memory warning.

2012-10-19 15:55:14.334inHyron[483:b903] viewWillUnload

2012-10-19 15:55:14.335 inHyron[483:b903]viewDidUnload

从log可以看出,当视图控制对象收到内存警告的时候,程序会执行viewWillUnload最后是执行viewDidUnload。

这样,一套的流程就完成了,不知道写的是否详细。。。。


转载:http://blog.youkuaiyun.com/weasleyqi/article/details/8090373

<think>我们正在讨论iOS开发中UIViewController的viewDidLoad方法。根据引用[1]和引用[2],viewDidLoad是UIViewController生命周期中的一个重要方法。 引用[1]指出:无论是从xib文件加载视图还是自己创建视图,viewDidLoad方法都会被调用,而且是在视图已经被加载后调用。同时强调,任何UI控件的创建都不应该在viewDidLoad方法中实现,因为这是xib文件或者loadView方法的任务。viewDidLoad只是通过nib或者loadView方法加载视图的一种拓展和补充机制。 引用[2]详细描述了UIViewController的生命周期,其中viewDidLoad在loadView之后被调用,此时整个视图层次(view hierarchy)已经放到内存中,可以移除一些视图,修改约束,加载数据等。 因此,我们可以总结如下: 1. viewDidLoad的调用时机:在视图控制器的视图被加载到内存之后调用,且在整个视图控制器的生命周期中只调用一次(除非视图被从内存中清除,但通常不会)。 2. 作用:用于进行一些初始化操作,但这些操作不应该包括创建视图层次(因为视图层次已经在loadView或从nib/storyboard加载完成),而应该是对已经加载的视图进行配置,例如设置控件的属性、加载数据、添加手势等。 3. 注意事项:避免在viewDidLoad中执行耗时操作,因为这会延迟视图的显示。如果确实需要执行耗时操作,应该使用异步方式。 使用场景: - 配置界面上的控件(例如设置文本、颜色、字体等) - 初始化数据模型,并更新界面 - 添加手势识别器 - 注册通知 - 设置委托 代码示例: ```objective-c - (void)viewDidLoad { [super viewDidLoad]; // 设置标题 self.title = @"首页"; // 设置背景色 self.view.backgroundColor = [UIColor whiteColor]; // 配置一个标签 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 200, 40)]; label.text = @"Hello, World!"; [self.view addSubview:label]; // 加载数据 [self loadData]; } - (void)loadData { // 异步加载数据 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 模拟网络请求 [NSThread sleepForTimeInterval:2.0]; dispatch_async(dispatch_get_main_queue(), ^{ // 更新UI }); }); } ``` 注意:在viewDidLoad中,视图的几何属性(如frame、bounds)可能还没有确定,因为此时还没有进行自动布局(Auto Layout)的计算。因此,如果代码依赖于视图的尺寸,最好在viewDidLayoutSubviews中处理。 另外,引用[1]特别强调,UI控件的创建不应该在viewDidLoad中,而应该在loadView方法中(如果是通过代码创建视图)或者由xib/storyboard完成。viewDidLoad只是对已经存在的视图进行配置。 总结:viewDidLoad是进行视图控制器初始化设置的重要方法,但要注意它只被调用一次,并且此时视图的几何属性可能还未确定。 相关问题: 1. viewDidLoad和loadView方法有什么区别? 2. 在viewDidLoad中为什么不能设置视图的frame? 3. 如果视图控制器是从storyboard创建的,viewDidLoad中应该做什么? 4. viewDidLoad和viewWillAppear的区别是什么? 5. 在viewDidLoad中执行网络请求是否合适?</think>### iOS开发中 `viewDidLoad` 方法详解 `viewDidLoad` 是 `UIViewController` 生命周期中的核心方法,在视图加载完成后触发。以下是详细解析: #### 1. **触发时机与作用** - **触发时机**:视图控制器完成视图加载后调用(在 `loadView` 方法之后)[^1][^2] - **关键特征**: ```mermaid graph LR A[initWithNibName] --> B[loadView] B --> C[viewDidLoad] C --> D[viewWillAppear] ``` - **作用**: - 执行**一次性初始化**操作 - 配置视图元素属性(颜色、字体等) - 加载初始数据 - 注册通知/委托 #### 2. **正确使用场景** ```objective-c - (void)viewDidLoad { [super viewDidLoad]; // ✅ 正确场景1:配置视图属性 self.titleLabel.textColor = [UIColor redColor]; self.tableView.delegate = self; // ✅ 正确场景2:初始化数据 [self loadInitialData]; // ✅ 正确场景3:添加手势识别 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)]; [self.view addGestureRecognizer:tap]; // ✅ 正确场景4:注册通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } ``` #### 3. **禁止操作与常见误区** - ❌ **禁止创建视图**: ```objective-c // 错误示例:创建新视图 UIView *newView = [[UIView alloc] init]; // 应在loadView中创建[^1] ``` - ❌ **避免布局操作**: ```objective-c // 错误示例:设置视图尺寸 self.button.frame = CGRectMake(0, 0, 100, 40); // 应在viewDidLayoutSubviews中处理[^2] ``` - ⚠️ **注意点**: - 每个视图控制器**仅调用一次**(除非手动释放视图) - 视图的几何属性(frame/bounds)尚未确定 - 不保证网络请求完成时界面已显示 #### 4. **与其他生命周期方法对比** | 方法 | 调用次数 | 典型用途 | 视图几何状态 | |---------------------|----------|-----------------------------------|--------------------| | `loadView` | 1次 | 创建视图层次 | 未设置 | | **`viewDidLoad`** | 1次 | 配置视图属性/加载数据 | 未确定 | | `viewWillAppear` | 多次 | 刷新数据/准备动画 | 已确定 | | `viewDidLayoutSubviews` | 多次 | 最终布局调整 | 最终确定 | #### 5. **最佳实践建议** 1. **保持轻量化**: ```objective-c // 耗时操作异步执行 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *data = [NSData dataWithContentsOfURL:imageURL]; dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = [UIImage imageWithData:data]; }); }); ``` 2. **内存管理**: ```objective-c - (void)dealloc { // 必须移除观察者 [[NSNotificationCenter defaultCenter] removeObserver:self]; } ``` 3. **状态恢复**: ```objective-c - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { [super encodeRestorableStateWithCoder:coder]; [coder encodeObject:self.dataArray forKey:@"data"]; } ``` #### 6. **调试技巧** ```objective-c - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"%@: viewDidLoad", self.class); // 检查视图层次 NSLog(@"View hierarchy: %@", self.view.subviews); } ``` > **关键总结**:`viewDidLoad` 是视图初始化的**核心枢纽**,适合执行**一次性配置**,但需避免视图创建和布局操作。它确保视图层次已加载,但尚未显示到屏幕[^1][^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值