iOS UIApplication全家福及程序啟動流程

一、UIApplication

1. 簡介:

  • UIApplication對象代表的就是iOS系統中的一個應用程序
  • 每一個應用都有自己的UIApplication對象,而且是單例的
  • 通過[UIApplication sharedApplication]可以獲得這個單例對象(通過打印兩個Application對象驗證)
  • 一個iOS程序啟動后創建的第一個對象就是UIApplication對象
  • 利用UIApplication對象,能進行一些應用級別的操作

2.常用屬性和方法:

// 應用程序代理
@property(nullable, nonatomic,assign) id<UIApplicationDelegate> delegate;

// 應用程序的主窗口
@property(nullable, nonatomic,readonly) UIWindow *keyWindow;

// 應用程序的窗口集合
@property(nonatomic,readonly) NSArray<__kindof UIWindow *>  *windows;

// 設置網絡狀態默認為NO,YES可以在系統狀態欄顯示一個轉動的菊花
@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible __TVOS_PROHIBITED; 

// 設置屏幕是否為常亮默認為NO,YES為常亮
@property(nonatomic,getter=isIdleTimerDisabled)       BOOL idleTimerDisabled;

// 用來顯示或者隱藏系統狀態欄默認為NO,設置YES為隱藏系統狀態欄
@property(readonly, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden __TVOS_PROHIBITED;

// 設置系統狀態欄的樣式默認為UIStatusBarStyleDefault
/*UIStatusBarStyle常用枚舉值
UIStatusBarStyleDefault //黑暗模式                
UIStatusBarStyleLightContent //燈光模式       
*/
@property(readonly, nonatomic) UIStatusBarStyle statusBarStyle __TVOS_PROHIBITED; 

// 可以設置應用程序圖標上面的數字
@property(nonatomic) NSInteger applicationIconBadgeNumber __TVOS_PROHIBITED; 
// 在iOS8.0以后 要使用UIApplication給應用程序設置圖標數字時,要注冊一個系統通知UIUserNotificationTypeBadge 就可以設置應用程序圖標上面的數字
/*  代碼示例:
    if ([[[UIDevice currentDevice] systemVersion] floatValue] > 8.0) {
        UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
    }
    [UIApplication sharedApplication].applicationIconBadgeNumber = 10;
*/

// 類方法,用來獲取UIApplication對象
+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead.");

// 可以打開一個指定的NSURL所指的資源
- (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS("");

3. 狀態欄的管理

  • 從iOS7開始,系統提供了2種管理狀態欄的方式
    • 通過UIViewController管理(每一個UIViewController都可以擁有自己不同的狀態欄)
    • 通過UIApplication管理(一個應用程序的狀態欄都由它統一管理)
  • 在iOS7之后,默認情況下,狀態欄都是由UIViewController管理的,若想通過UIApplication進行管理,則需要配置plist文件


    app管理.png
// 示范代碼:
// 隱藏系統狀態欄
[UIApplication sharedApplication].statusBarHidden = YES;
// 設置系統狀態欄樣式
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

// 隱藏系統狀態欄帶動畫
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
// 設置系統狀態欄樣式帶動畫
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

4. openURL方法的應用

/*
NSURL統一資源定位符  格式 > 協議://路徑
*/
// 創建UIApplication對象
UIApplication  *app = [UIApplication sharedApplication];

// 打電話 tel為打電話協議
[app openURL:[NSURL URLWithString:@"tel://10086"]];

// 發短信 sms為發短信協議
[app openURL:[NSURL URLWithString:@"sms://10086"]];

// 打開網址 http為上網協議
[app openURL:[NSURL URLWithString:@"http://www.ithemima.com"]];

// 發送郵件 mailto為發送郵件協議
[app openURL:[NSURL URLWithString:@"mailto://zhangsan@itcast.cn"]];

二、應用程序的狀態介紹

應用程序狀態.png
  • Not running (未運行狀態):應用程序未啟動或應用程序被系統終止。
  • Inactive(不活動狀態):程序在前臺運行,但不能接收事件。當應用要從一個狀態切換到另一個不同的狀態時,中途過渡會短暫停留在此狀態。
  • Active(活動):程序在前臺運行且能接受事件。這是應用在前臺運行時所處的正常狀態。
  • Background(后臺):應用處在后臺運行,并且還在執行代碼。大多數將要進入Suspended狀態的應用,會先短暫進入此狀態。如果應用請求更多額外的執行時間,該應用會在此狀態保持更長一段時間。另外,如果一個應用要求啟動時直接進入后臺運行,這樣的應用會直接從Not running狀態進入Background狀態,中途不會經過Inactive狀態。比如,沒有界面的應用,總之,如果應用直接進入Background狀態,該應用界面不會被顯示出來。
  • Suspended(掛起):應用處在后臺,并且沒有執行任何代碼。系統會自動將應用轉入該狀態,應用依然駐留內存,但不執行任何程序代碼。當系統發生低內存警告時,系統會將處于Suspend狀態的應用徹底移除內存,從而為前臺應用釋放更多的內存。

三、UIApplicationDelegate

1.簡介:

UIApplicationDelegate定義的方法主要工作之一就是跟蹤應用程序的狀態變化,當應用程序發生重大的運行時事件時如:應用啟動完畢、低內存警告和應用程序終止,進入前臺、后臺、可見等的時候會在適當的時機通知代理做出響應

2.代理方法及對應的執行時機

// 應用程序啟動完畢
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSLog(@"應用程序啟動完畢");
    return YES;
}
// 應用程序變為不活躍狀態
- (void)applicationWillResignActive:(UIApplication *)application {

    NSLog(@"應用程序變為不活躍狀態");
}
// 應用程序進入后臺
- (void)applicationDidEnterBackground:(UIApplication *)application {
   /**
     1.停止timers并終止其他周期性的任務。
     2.停止任何正在運行的元數據查詢。
     3.不要初始化任何新的任務。
     4.暫停電影播放(在AirPlay上播放的除外)。
     5.游戲進入暫停狀態。
     6.暫停所有執行非關鍵代碼的調度隊列和操作隊列(即使處于Inactive狀態,依然可以繼續處理網絡請求和其他耗時的后臺任務)。
     */
    NSLog(@"應用程序進入后臺");
}
// 應用程序進入前臺
- (void)applicationWillEnterForeground:(UIApplication *)application {
    NSLog(@"應用程序進入前臺");
}
// 應用程序變為活躍狀態
- (void)applicationDidBecomeActive:(UIApplication *)application {
    // 恢復在- (void)applicationWillResignActive:(UIApplication *)application方法中做的所有任務
    // 但游戲的恢復應該讓用戶自己決定。
    NSLog(@"應用程序變為活躍狀態");
}
// 應用程序即將終止
- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@"應用程序即將終止");
}
// 應用程序收到內存警告
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application{
    NSLog(@"應用程序收到內存警告");
}

四、UIApplicationMain

  • UIApplicationMain是程序主函數中執行的一個函數
int UIApplicationMain ( int argc, char * _Nonnull argv[], NSString *principalClassName, NSString *delegateClassName );
   /*  
   1.返回值為一個int類型  
   2.第一個參數:對應main函數的第一個參數:參數個數  
   3.第二個參數:對應main函數的第二個參數:參數列表  
   4.第三個參數:principalClassName    UIApplication類或子類的類名字,如果為nil.默認為UIApplication  
   5.第四個參數:delegateClassName  應用程序代理類的名字
    */  
  • UIApplicationMain函數會根據principalClassName創建 UIApplication對象,根據delegateClassName創建一個delegate對象,并將該delegate對象賦值給UIApplication對象中的delegate屬性
  • 接著會建立應用程序的Main Runloop(事件循環),進行事件的處理(首先會在程序完畢后調用delegate對象的application:didFinishLaunchingWithOptions:方法)
  • 程序正常退出時UIApplicationMain函數才返回

五、應用程序的啟動

iOS程序啟動過程.png

程序啟動的完整過程:

  1. 先執行main函數,main內部會調用UIApplicationMain函數,該函數的聲明如下:
 int UIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName)。
 //argc、argv:標準main函數的參數,直接傳遞給UIApplicationMain進行相關處理即可
 //principalClassName:指定應用程序類,該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為默認值
//delegateClassName:指定應用程序類的代理類,該類必須遵守UIApplicationDelegate協議。
  1. 在UIApplicationMain函數里面做了如下幾件事情:
    (1). 根據傳入的第三個參數創建UIApplication對象或它的子類對象。如果該參數為nil,直接使用該UIApplication來創建。(該參數只能傳人UIApplication或者是它的子類)
    (2). 根據傳入的第四個參數創建AppDelegate對象,并將該對象賦值給第1步創建的 UIApplication對象的delegate屬性。
    (3). 開啟一個事件循環,循環監控應用程序發生的事件。每監聽到對應的系統事件時,就會通知AppDelegate。

3、接著加載控制器view分兩種情況

  • 有storyboard

  • 1.應用程創建一個UIWindow對象(繼承自UIView),并設置為AppDelegate的window屬性。

  • 2.加載Info.plist文件,讀取最主要storyboard文件的名稱。

  • 3.加載最主要的storyboard文件,創建白色箭頭所指的控制器對象。并且設置控制器為UIWindow的rootViewController屬性(根控制器)。

  • 4.展示UIWindow,展示之前會將添加rootViewController的view到UIWindow上面(在這一步才會創建控制器的view),其內部會執行該行代碼:[window addSubview: window.rootViewController.view];

  • 沒有storyboard

    • 1.首先會調用delegate對象的application:didFinishLaunchingWithOptions:方法。
    • 2.在application:didFinishLaunchingWithOptions:方法中需要主動創建 UIWindow對象。并設置為AppDelegate的window屬性。
    • 3.主動創建一個 UIViewController對象,并賦值給window的rootViewController屬性。
      1. 調用 window的makeKeyAndVisible方法顯示窗口。
  • 注:如果重寫了loadView方法,則會通過UIViewController中的loadView方法中的代碼創建view,而不會加載storyboard
    4、顯示控制的view到手機屏幕

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容