APP的“状态” 及 UIApplicationDelegate方法

APP的状态:

Not running ( 未运行 ): 程序没启动

Inactive ( 未激活 ): 程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态。

Active ( 激活 ): 程序在前台运行而且接收到了事件。这也是前台的一个正常的模式。

Backgroud ( 后台 ): 程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态。

Suspended ( 挂起 ): 程序在后台但是却不能执行代码。系统会自动把程序变成这个状态而且不会发出通知
当挂起时,程序还是停留内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。


APP的DidEnterBackground/WillEnterForeground:
  • 1.进入后台 ----- DidEnterBackground
    当程序进入后台状态时,名为“applicationDidEnterBackground”委托方法会被调用:

    - (void)applicationDidEnterBackground:(UIApplication *)application {    }
    

  • 2.进入前台 ----- WillEnterForeground
    当程序进入后台状态时,名为“applicationWillEnterForeground”委托方法会被调用:

    - (void)applicationWillEnterForeground:(UIApplication *)application {    }
    


APP的DidBecomeActive/ResignActive:
  • 1.挂起 ----- WillResignActive
    当 有电话进来 或者 锁屏(拉下状态栏、双击Home键使App界面上移) 的时候,你的应用程会挂起。而在这个时候,UIApplicationDelegate委托 会收到通知,调用“applicationWillResignActive”方法,可以重写这个方法,添加 挂起之前的工作,比如:关闭网络、保存数据。

    - (void)applicationWillResignActive:(UIApplication*)application {    }   
    

当程序被挂起后,程序将不会在 后台运行

  • 2.复原 ----- DidBecomeActive
    当程序复原时,另一个名为“applicationDidBecomeActive”委托方法会被调用,在此你可以通过之前挂起前保存的数据恢复 你的应用程序:

    - (void)applicationDidBecomeActive:(UIApplication*)application {    }
    

注意:应用程序在启动时,在调用了“applicationDidFinishLaunching”方法之后 同样也会 调用“applicationDidBecomeActive”方法!!!所以要确保你的代码能够分清 程序的复原启动,避免出现逻辑上的bug。


APP的终止

当用户 按下按钮 或者 关机,程序都会被终止。当一个程序将要正常终止时,会调用“applicationWillTerminate”方法。 ⚠️:但是如果点击主按钮 强制退出,则不会调用该方法。
这个方法用于执行剩下的 清理工作~ 比如:所有的连接都能正常关闭,并在程序退出之前执行任何其他的必要的工作:

  - (void)applicationWillTerminate:(UIApplication*)application {    }



APP状态改变的代理方法:
  // 程序 开始运行
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      // Override point for customization after application launch.
      return YES;
  }

  // 程序 挂起
  - (void)applicationWillResignActive:(UIApplication *)application {
      /* Sent when the application is about to move from active to inactive state. This can occur 
      for certain types of temporary interruptions (such as an incoming phone call or SMS message) 
      or when the user quits the application and it begins the transition to the background state.  
      */

      /* Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering 
       callbacks. Games should use this method to pause the game.
      */

  }

  // 程序 进入后台
  - (void)applicationDidEnterBackground:(UIApplication *)application {
      /* Use this method to release shared resources, save user data, invalidate timers, and store 
      enough application state information to restore your application to its current state in case 
      it is terminated later.
      */

      /* If your application supports background execution, this method is called instead of 
      applicationWillTerminate: when the user quits.
      */

  }

  // 程序 进入前台
  - (void)applicationWillEnterForeground:(UIApplication *)application {
      /* Called as part of the transition from the background to the active state; here you can 
      undo many of the changes made on entering the background.
      */

  }

  // 程序 重新激活
  - (void)applicationDidBecomeActive:(UIApplication *)application {
      /* Restart any tasks that were paused (or not yet started) while the application was inactive. 
      If the application was previously in the background, optionally refresh the user interface.
      */

  }

  // 程序 终止
  - (void)applicationWillTerminate:(UIApplication *)application {
      /* Called when the application is about to terminate. Save data if appropriate. 
      See also applicationDidEnterBackground:.
      */

  }




应用运行过程状态变化 对应的“UIApplicationDelegate”方法执行:
  • 首次运行:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    - (void)applicationDidBecomeActive:(UIApplication *)application
    

  • 首次关闭(home):

    - (void)applicationWillResignActive:(UIApplication *)application
    - (void)applicationDidEnterBackground:(UIApplication *)application
    

  • 再次运行:

    - (void)applicationWillEnterForeground:(UIApplication *)application
    - (void)applicationDidBecomeActive:(UIApplication *)application
    

  • 再次关闭:

    - (void)applicationWillResignActive:(UIApplication *)application
    - (void)applicationDidEnterBackground:(UIApplication *)application
    


进阶:

  • “点击桌面图标,正常启动App” 或者 “杀死进程后点击推送消息,启动App” :
    1.application:willFinishLaunchingWithOptions
    2.application:application:didFinishLaunchingWithOptions
    3.applicationDidBecomeActive
    4.application:didRegisterForRemoteNotificationsWithDeviceToken // 接收、处理消息通知

  • 拖下通知中心/双击Home键,使App界面上移
    applicationWillResignActive

  • 拖上通知中心/再双击Home键,使App界面恢复原位
    applicationDidBecomeActive

  • 按Home键,使App 进入后台
    1.applicationWillResignActive
    2.applicationDidEnterBackground

  • 点击App图标,使App从后台 恢复至前台
    1.applicationWillEnterForeground
    2.applicationDidBecomeActive

  • 点击通知中心里面的远程推送,使App从后台 进入前台
    1.applicationWillEnterForeground
    2.application:didReceiveRemoteNotification // 接收、处理消息通知
    3.applicationDidBecomeActive

  • 上滑 或者 按住App图标,选择减号图标,杀死App进程(终止程序)
    applicationWillTerminate

  • 从APP切换到微信之类的其他应用之后,再切换回来
    1.applicationWillEnterForeground
    2.application:openURL:sourceApplication // 应用间⭐️传值⭐️
    3.applicationDidBecomeActive


内容来源:UIApplicationDelegate里面最常用的几个函数执行顺序小结



最后,推荐几个比较直观的图片:
程序状态变化图
加载应用程序进入前台
加载应用程序进入后台
响应中断 (比如有电话打进来).png
转到后台运行
返回前台运行



The Main Run Loop ————— 主运行循环
Main Run Loop负责 处理用户相关的事件。UIApplication对象在程序启动时启动Main Run Loop,它处理事件更新视图的界面。看Main Run Loop就知道,它是运行在程序的主线程上的。这样保证了接收到用户相关操作的事件是按顺序 处理的。

处理事件的架构图

用户操作设备,相关的操作事件被系统生成并通过UIKit的指定端口分发。事件在内部排成队列,一个个的分发到Main Run Loop 去做处理。UIApplication对象是第一个接收到时间的对象,它决定事件如何被处理。触摸事件分发到主窗口,窗口再分发到对应触发 触摸事件的View。其他的事件通过其他途径分发给其他对象变量做处理。

大部分的事件可以在你的应用里分发,类似于触摸事件,远程操控事件(线控耳机等) 都是由app的 responder objects 对象处理的。
Responder objects 在你的app里到处都是,比如:UIApplication 对象,view对象,view controller 对象,都是resopnder objects。大部分事件的目标都指定了resopnder object,不过事件也可以传递给其他对象。比如,如果view对象不处理事件,可以传给父类view或者view controller。


图片及内容来源:应用程序生命周期















goyohol's essay

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容