美文网首页
UIApplicationDelegate 与UIViewCon

UIApplicationDelegate 与UIViewCon

作者: 罂粟之城 | 来源:发表于2019-07-29 13:28 被阅读0次

    UIApplicationDelegate

    每个 iOS 应用程序都有一个 UIApplicationUIApplication 是 iOS 应用程序的开始并且负责初始化并显示 UIWindow,并负责加载应用程序的第一个 UIView 到 UIWindow 窗体中。

    UIApplication 的另一个任务是帮助管理应用程序的生命周期,而 UIApplication 通过一个名字为 UIApplicationDelegate 的代理类来履行这个任务。尽管 UIApplication 会负责接收事件,而 UIApplicationDelegate 则决定应用程序如何去响应这些事件,UIApplicationDelegate 可以处理的事件包括应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警 告)。

    UIApplicationStep.png

    通常是没必要修改UIApplication的,只需要知道 UIApplication 接收系统事件即可。处理系统事件需要编写一个继承自 UIApplicationDelegate 接口的类,而 UIApplicationDelegate 接口提供生命周期函数来处理应用程序以及应用程序的系统事件。我们新建项目的时候,往往会自动生成一个继承自 UIApplicationDelegate 接口的类AppDelegate。

    UIApplicationDeleagte 的生命周期

    #pragma mark 在应用程序加载完毕之后调用
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        NSLog(@"didFinishLaunchingWithOptions-加载完毕");
        
        // 初始化一个窗口
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        
        // 传入xib文件名来初始化一个控制器
        self.viewController = [[[TestViewController alloc] initWithNibName:@"MJViewController" bundle:nil] autorelease];
        
        // 设置窗口的根控制器
        self.window.rootViewController = self.viewController;
        // 上面的代码内部执行了下面代码的操作
        // [self.window addSubview:self.viewController.view];
        
        // 窗口不会默认显示,需要调用方法来显示
        // keyWindow是主窗口,只有主窗口才能跟用户正常交互
        [self.window makeKeyAndVisible];
        // self.window.hidden = NO;
        return YES;
    }
    
    #pragma mark 程序不活跃状态的时候调用(不能跟用户进行交互了)
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        NSLog(@"applicationWillResignActive-不活跃状态");
    }
    
    #pragma mark 当应用程序进入后台的时候调用(点击HOME键)
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        NSLog(@"applicationDidEnterBackground-进入后台");
    }
    
    #pragma mark 当应用程序进入前台的时候调用
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        NSLog(@"applicationWillEnterForeground-进入前台");
    }
    
    #pragma mark 当应用程序处于活跃状态的时候调用
    // 处于不活跃状态之后才可以跟用户进行交互
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        NSLog(@"applicationDidBecomeActive-活跃状态");
    }
    
    #pragma mark 程序在某些情况下被终结时会调用这个方法
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        NSLog(@"applicationWillTerminate-被关闭");
    }
    

    下面输出:

    程序启动后:
    
            didFinishLaunchingWithOptions   -- 加载完毕
            applicationDidBecomeActive  -- 处于活跃状态
    
    按下home键:
    
            applicationWillResignActive -- 处于不活跃状态
            applicationDidEnterBackground -- 进入后台
    
    再按程序:
            applicationWillEnterForeground -- 进入前台
            applicationDidBecomeActive -- 处于活跃状态
    

    UIViewController

    UIViewController 是负责内部的各个 UIView 加载显示和移除卸载,下面是 UIView的加载过程

    UIViewController-UIViewLoad.png

    从图中可以看到,在 view 加载过程中首先会调用 loadView 方法,在这个方法中主要完成一些关键view的初始化工作,比如UINavigationViewControllerUITabBarController 等容器类的 ViewController;

    接下来就是加载view,加载成功后,会接着调用 viewDidLoad 方法,这里要记住的一点是,在 loadView 之前,是没有view的,也就是说,在这之前,view还没有被初始化。完成 viewDidLoad 方法后,ViewController里面就成功的加载view了,如上图右下角所示。

    在Controller中创建view有两种方式,一种是通过代码创建、一种是通过 StoryboardInterface Builder 来创建,后者可以比较直观的配置view的外观和属性,Storyboard 配合IOS6后推出的 AutoLayout,应该是Apple之后主推的一种UI定制解决方案。

    UIView 卸载过程:

    UIViewController-UIviewUnload.png

    从图中可以看到,当系统发出内存警告时,会调用 didReceiveMemoeryWarning 方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用 viewDidUnload 方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在 viewDidUnload 方法中调用 self.myView = nil ;

    UIViewController 生命周期

    ViewController的生命周期中各方法执行流程如下图:

    UIViewCroller-LifeCycle.png

    各个方法调用流程:

    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            NSLog(@"ViewController 初始化");
        }
        return self;
    }
    
    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            NSLog(@"ViewController 从归档初始化");
        }
        return self;
    }
    
    - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            self.view.backgroundColor = [UIColor whiteColor];
            NSLog(@"ViewController 从xib初始化");
        }
        return self;
    }
    
    - (void)loadView {
        [super loadView];
        NSLog(@"ViewController 开始加载视图");
    }
    
    - (void)loadViewIfNeeded
    
    /**
      这个方法用的时候,outlet还没有连接起来,是view Controller刚从storyboard建的时候,没有完全建好
        不过可能有一些事情要在这个方法里面完成,比如splitViewDelegate,需要在非常早期完成。
    */
    - (void)awakeFromNib{
        [super awakeFromNib]; 
        NSLog(@"ViewController awakeFromNib");
    }
    
    /**
         用这个的时候,ViewController已经完全好了,outlet也已经连接好了。但是还没有在屏幕上显示出来。
        这个方法里面可以放很多设置的代码。
        这个方法执行的时候,view的bounds还没有。先load,再appear嘛。
    */
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"ViewController 已经加载视图");
    }
    
    - (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];
        NSLog(@"ViewController 开始布局子视图");
    }
    
    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
        NSLog(@"ViewController 完成布局子视图");
    }
    
    /**
         这个方法调用的时候,bounds已经有了。
        你的视图只会loaded一次,但是会appear或者disappear很多次。所以不变的东西,放在viewDidLoad里面。和几何相关的,放在viewWillAppear里面。这点对项目的优化很重要的
        就好似顶层的view,旋转ipad什么的都需要改变顶层的view的大小,当一个view controller的生命周期到这里的时候,就可以在这里的最后时刻来调整view的排列或者几何特性。
        这里也设置做一些lazy execution for performance.比如:需要按一个button,出现一个view什么的。
        这里设置,开销很大。耗时很长的事情最好在viewWillAppear里另开一个线程运行,然后在view里面放一个小小的spinning wheel。
    */
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        NSLog(@"ViewController 即将显示");
    }
    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        NSLog(@"ViewController 已经显示");
    }
    
    /**
        这个方法当然是要消失的时候啦。要消失的时候,还是记得现在的运行情况的。所以可以记得scroll的position啦。
       但是,不要在这个方法里面写太多的东西哦,app会崩溃的。
    */
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        NSLog(@"ViewController 即将消失");
    }
    
    - (void)viewDidDisappear:(BOOL)animated {
        [super viewDidDisappear:animated];
        NSLog(@"ViewController 已经消失");
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        NSLog(@"ViewController 收到内存警告");
    }
    
    
    @end
    

    相关文章

      网友评论

          本文标题:UIApplicationDelegate 与UIViewCon

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