一、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
程序啟動的完整過程:
- 先執行main函數,main內部會調用UIApplicationMain函數,該函數的聲明如下:
int UIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName)。
//argc、argv:標準main函數的參數,直接傳遞給UIApplicationMain進行相關處理即可
//principalClassName:指定應用程序類,該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為默認值
//delegateClassName:指定應用程序類的代理類,該類必須遵守UIApplicationDelegate協議。
- 在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屬性。
- 調用 window的makeKeyAndVisible方法顯示窗口。
注:如果重寫了loadView方法,則會通過UIViewController中的loadView方法中的代碼創建view,而不會加載storyboard
4、顯示控制的view到手機屏幕