iOS开发经验总结iOS-swiftiOS移动开发

UIViewController Lifecycle

2015-03-24  本文已影响743人  Saxon_Geoffrey

作为每个初学者99.9%会接触到的UIViewController,这篇文章主要来讲讲UIViewController的生命周期。

我们从一个例子来证明这个结论:

如下是storyBoard的配置:

ViewController.m

@interface ViewController ()
@property (nonatomic,strong)NSString *str;
@property (weak, nonatomic) IBOutlet UIButton *button;
@end

下面是生命周期有关的方法:

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        NSLog(@"0");
    }
    return self;
}

-(void)awakeFromNib{
    NSLog(@"1");
}

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

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    NSLog(@"3");
}

-(void)viewWillLayoutSubviews{
    NSLog(@"4");
}

-(void)viewDidLayoutSubviews{
    NSLog(@"5");
}

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSLog(@"6");
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    NSLog(@"7");
}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    NSLog(@"8");
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

运行后点击按钮跳转到第二个控制器,打印如下:

2015-03-24 00:00:44.771 test[2925:305854] 0
2015-03-24 00:00:44.772 test[2925:305854] 1
2015-03-24 00:00:44.778 test[2925:305854] 2
2015-03-24 00:00:44.779 test[2925:305854] 3
2015-03-24 00:00:44.785 test[2925:305854] 4
2015-03-24 00:00:44.785 test[2925:305854] 5
2015-03-24 00:00:44.788 test[2925:305854] 6
2015-03-24 00:00:47.982 test[2925:305854] 7
2015-03-24 00:00:47.987 test[2925:305854] 4
2015-03-24 00:00:47.988 test[2925:305854] 5
2015-03-24 00:00:48.489 test[2925:305854] 8

也就是说,ViewController的生命周期基本是下面的步骤:

Instantiated :初始化
awakeFromNib:主要做一些viewDidLoad之前的事情
outlets 的配置
viewDidLoad
viewWillLayoutSubviews和viewDidLayoutSubviews:
viewWillAppear和viewDidAppear
viewWillDisappear: and viewDidDisappear
didReceiveMemoryWarning:收到内存警告
现在不存在“unload”方法

你可能会问为什么outlets 的配置介于awakeFromNib和viewDidLoad之间呢,我们可以通过下面的代码证实一下:

-(void)awakeFromNib{
    NSLog(@"1");
    [_button setTitle:@"哈哈" forState:UIControlStateNormal];
}

运行结果发现按钮的标题并没有发生变化,我们再看:

- (void)viewDidLoad {
    [super viewDidLoad];
    [_button setTitle:@"呵呵" forState:UIControlStateNormal];
    NSLog(@"2");
}

运行结果发现按钮的标题发生变化了,所以可以知道outlets 的配置是介于awakeFromNib和viewDidLoad,这点比较重要。

1.initWithCoder ,
关于initWithCoder ,你是不是觉得它更应该出现在数据持久化中呢?确实它是一个NSCoding protocol, 所以你在UIViewController的文档中不会找到它。initWithCoder 是一个类在IB中创建但在xocde中被实例化时被调用的。你可以理解为是一个解固过程,所以在这个时候view还没初始化,你可以完成一些需要在view未初始化之前调用的方法。注意这个方法在生命周期中只会调用一次。

2.awakeFromNib
当.nib文件或storyBoard文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件或storyBoard文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象时执行awakeFromNib

如果你不是从.nib文件或storyBoard文件中加载view,你可以在loadView方法通过代码初始化view。

3.viewWillLayoutSubviews和viewDidLayoutSubviews

viewWillAppear和viewDidAppear前会调用改方法,主要是和布局相关。在当几何方向改变时也会再次调用以下方法,例如旋转方向变化。
(当选择方向改变还会收到 will/didRotateTo/From messages)

再说下可能会看到的initWithNibName 和 loadNibNamed。
主要是用于加载子view,使用此方法加载用户界面(xib文件)到我们的代码中,这样,可以通过操作这个加载进来的(xib)对象,来操作xib文件内容。 它们之间的区别是initWithNibName方法:是延迟加载,这个View上的控件是 nil 的,只有到 需要显示时,才会不是 nil 。
loadNibNamed方法:即时加载,用该方法加载的xib对象中的各个元素都已经存在。

- (void)submitShare:(id)sender
{
    if (![self checkInputContentLegal]) {
        return;
    }
    [_textView resignFirstResponder];
    if (!_locationEnable) {//如果不显示地理位置
        _latitude = 0;
        _longtitude = 0;
        NSLog(@"不显示地理位置");
    }else{
        NSLog(@"显示地理位置,%f,%f",_latitude,_longtitude);
    }
    NSString *accseeToken = [AccountTool sharedAccountTool].account.accessToken;
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:kUploadURL]];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    __weak typeof(self) weakSelf = self;
    NSString *encodeStatus = _textView.text;
    if (_images.count == 0) {
        [manager POST:@"2/statuses/update.json"
           parameters:@{@"access_token": accseeToken,
                             @"status" : encodeStatus,
                             @"visible" : @(_intVisible),
                             @"lat" : @(_latitude),
                             @"long" : @(_longtitude)}
              success:^(NSURLSessionDataTask *task, id responseObject) {
                  NSLog(@"发送成功");
                  [self showSuccessHUD];
                  [self performSelector:@selector(back) withObject:self afterDelay:1.5];
                }
              failure:^(NSURLSessionDataTask *task, NSError *error) {
                  [self showFailHUD];
                  NSLog(@"发送失败");
                }];
    }else{
        [manager POST:@"2/statuses/upload.json"
           parameters:@{@"access_token": accseeToken,
                           @"status" : encodeStatus,
                           @"visible" : @(_intVisible),
                           @"lat" : @(_latitude),
                           @"long" : @(_longtitude)}
            constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                NSMutableArray *images = [NSMutableArray arrayWithArray:weakSelf.images];
                for (id asset in images) {
                    NSData *data = nil;
                    if ([asset isKindOfClass:[UIImage class]]) {
                        data = UIImageJPEGRepresentation(asset, 0.4);
                    }
                    if ([asset isKindOfClass:ALAsset.class]) {
                        UIImage *original = [UIImage imageWithCGImage: [[asset defaultRepresentation] fullScreenImage]];
                        data = UIImageJPEGRepresentation(original, 0.4);
                    }
                    [formData appendPartWithFileData:data name:@"pic" fileName:@"pic.jpg" mimeType:@"multipart/form-data"];
                    //新浪开放的API一次只能上传一张图片,选择多张的时候会使用最后一张,通过调用[http://open.weibo.com/wiki/2/statuses/upload_pic]() 接口生成高级接口statuses/upload_url_text中的参数pic_id,可以实习上传多张图片
                }
            } success:^(NSURLSessionDataTask *task, id responseObject) {
                NSLog(@"发送成功");
                [self back];
            } failure:^(NSURLSessionDataTask *task, NSError *error) {
                [self showFailHUD];
            }];
    }
}
上一篇下一篇

猜你喜欢

热点阅读