程式啟動原理和UIApplication
一、UIApplication
1.簡單介紹
-
UIApplication物件是應用程式的象徵,
一個UIApplication物件就代表一個應用程式
; -
每一個應用都有自己的UIApplication物件,而且是單例的
,如果試圖在程式中新建一個UIApplication物件,那麼將報錯提示; -
通過
[UIApplication sharedApplication]
可以獲得這個單例物件; -
一個iOS程式啟動後建立的第一個物件就是
UIApplication物件
,且只有一個
(通過程式碼獲取兩個UIApplication物件,列印地址可以看出地址是相同的)。 -
利用
UIApplication物件
,能進行一些應用級別的操作
1.2 應用級別的操作示例:
- 設定應用程式圖示右上角的
紅色提醒數字
(如QQ訊息的時候,圖示上面會顯示1,2,3條新資訊等。)
@property(nonatomic) NSInteger applicationIconBadgeNumber;
程式碼實現和效果:
- (void)viewDidLoad
{
[super viewDidLoad];
//建立並新增一個按鈕
UIButton *btn=[[UIButton alloc]initWithFrame:CGRectMake(100, 100, 60, 30)];
[btn setTitle:@"按鈕" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor brownColor]];
[btn addTarget:self action:@selector(onClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
-(void)onClick
{
NSLog(@"按鈕點選事件");
//錯誤,只能有一個唯一的UIApplication物件,不能再進行建立
// UIApplication *app=[[UIApplication alloc]init];
//通過sharedApplication獲取該程式的UIApplication物件
UIApplication *app=[UIApplication sharedApplication];
app.applicationIconBadgeNumber=123;
}
- 設定聯網指示器的可見性
@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
程式碼和效果:
//設定指示器的聯網動畫
app.networkActivityIndicatorVisible=YES;
- 管理狀態列
從iOS7開始
,系統提供了2種管理狀態列的方式
:
a.通過UIViewController管理(每一個UIViewController都可以擁有自己不同的狀態列).
在iOS7中,預設情況下
,狀態列都是由UIViewController管理的
,UIViewController實現下列方法就可以輕鬆管理狀態列的可見性和樣式:
//狀態列的樣式
-(UIStatusBarStyle)preferredStatusBarStyle;
//狀態列的可見性
-(BOOL)prefersStatusBarHidden;
程式碼設定如下:
-(UIStatusBarStyle)preferredStatusBarStyle
{
//設定為白色
//return UIStatusBarStyleLightContent;
//預設為黑色
return UIStatusBarStyleDefault;
}
#pragma mark-設定狀態列是否隱藏(否)
-(BOOL)prefersStatusBarHidden
{
return NO;
}
b.通過UIApplication管理(一個應用程式的狀態列都由它統一管理)
如果想利用UIApplication來管理狀態列
,首先得修改Info.plist的設定
:
程式碼:
//通過sharedApplication獲取該程式的UIApplication物件
UIApplication *app=[UIApplication sharedApplication];
app.applicationIconBadgeNumber=123;
//設定指示器的聯網動畫
app.networkActivityIndicatorVisible=YES;
//設定狀態列的樣式
//app.statusBarStyle=UIStatusBarStyleDefault;//預設(黑色)
//設定為白色+動畫效果
[app setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
//設定狀態列是否隱藏
app.statusBarHidden=YES;
//設定狀態列是否隱藏+動畫效果
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
補充:
既然兩種都可以對狀態列進行管理,那麼什麼時候該用什麼呢?
如果狀態列的樣式只設定一次
,那就用UIApplication來進行管理
;
如果狀態列是否隱藏,樣式不一樣
那就用控制器進行管理
。
UIApplication來進行管理有額外的好處,可以提供動畫效果。
- openURL:方法
UIApplication有個功能十分強大的openURL:方法
- (BOOL)openURL:(NSURL*)url;
openURL:方法的部分功能有:
打電話
UIApplication *app = [UIApplicationsharedApplication]; [app openURL:[NSURLURLWithString:@"tel://10086"]];
發簡訊
[app openURL:[NSURLURLWithString:@"sms://10086"]];
發郵件
[app openURL:[NSURLURLWithString:@"mailto://12345@qq.com"]];
開啟一個網頁資源
[app openURL:[NSURLURLWithString:@"http://ios.itcast.cn"]];
開啟其他app程式
openURL方法,可以開啟其他APP。
URL補充:
URL:統一資源定位符,用來唯一的表示一個資源。
URL格式:
協議頭://主機地址/資源路徑
網路資源:
http/ ftp等 表示百度上一張圖片的地址
例如:http://www.baidu.com/images/20140603/abc.png
本地資源:
file:///users/apple/desktop/abc.png(主機地址省略)
二、UIApplication Delegate
1.簡單說明
所有的移動作業系統都有個致命的缺點:
app很容易受到打擾。比如一個來電或者鎖屏會導致app進入後臺甚至被終止。
還有很多其它類似的情況會導致app受到干擾,在app受到干擾時,會產生一些系統事件
,這時UIApplication
會通知它的delegate物件
,讓delegate代理來處理這些系統事件。
作用:當被打斷的時候,通知代理進入到後臺。
每次新建完專案,都有個帶有“AppDelegate”字眼的類,它就是UIApplication的代理,NJAppDelegate預設已經遵守了UIApplicationDelegate協議,已經是UIApplication的代理。
2.代理方法
1 #import "YYAppDelegate.h"
2
3 @implementation YYAppDelegate
4
5 // 當應用程式啟動完畢的時候就會呼叫(系統自動呼叫)
6 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
7 {
8 NSLog(@"didFinishLaunchingWithOptions");
9 return YES;
10 }
11
12 // 即將失去活動狀態的時候呼叫(失去焦點, 不可互動)
13 - (void)applicationWillResignActive:(UIApplication *)application
14 {
15 NSLog(@"ResignActive");
16 }
17
18 // 重新獲取焦點(能夠和使用者互動)
19 - (void)applicationDidBecomeActive:(UIApplication *)application
20 {
21 NSLog(@"BecomeActive");
22 }
23
24 // 應用程式進入後臺的時候呼叫
25 // 一般在該方法中儲存應用程式的資料, 以及狀態
26 - (void)applicationDidEnterBackground:(UIApplication *)application
27 {
28 NSLog(@"Background");
29 }
30
31 // 應用程式即將進入前臺的時候呼叫
32 // 一般在該方法中恢復應用程式的資料,以及狀態
33 - (void)applicationWillEnterForeground:(UIApplication *)application
34 {
35 NSLog(@"Foreground");
36 }
37
38 // 應用程式即將被銷燬的時候會呼叫該方法
39 // 注意:如果應用程式處於掛起狀態的時候無法呼叫該方法
40 - (void)applicationWillTerminate:(UIApplication *)application
41 {
42 }
43
44 // 應用程式接收到記憶體警告的時候就會呼叫
45 // 一般在該方法中釋放掉不需要的記憶體
46 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
47 {
48 NSLog(@"MemoryWarning");
49 }
50 @end
應用程式一般有五個狀態:官方文件app.states
三、程式啟動原理
3.1 UIApplicationMain
main函式
中執行了一個UIApplicationMain
這個函式:
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
argc、argv:直接傳遞給UIApplicationMain進行相關處理即可
principalClassName:
指定應用程式類名(app的象徵
),該類必須是UIApplication(或子類)。如果為nil
,則用UIApplication類作為預設值
delegateClassName:指定
應用程式的代理類
,該類必須遵守UIApplicationDelegate協議
-
UIApplicationMain函式會根據
principalClassName
建立UIApplication物件
,根據delegateClassName
建立一個delegate物件
,並將該delegate物件
賦值給UIApplication物件中的delegate屬性 -
接著會
建立應用程式的Main Runloop(事件迴圈)
,進行事件的處理(首先會在程式完畢後呼叫delegate物件的application:didFinishLaunchingWithOptions:方法) -
程式正常退出時UIApplicationMain函式才返回
#import <UIKit/UIKit.h>
#import "YYAppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
// return UIApplicationMain(argc, argv, nil, NSStringFromClass([YYAppDelegate class]));
// return UIApplicationMain(argc, argv, @"UIApplication", NSStringFromClass([YYAppDelegate class]));
/*
argc: 系統或者使用者傳入的引數個數
argv: 系統或者使用者傳入的實際引數
1.根據傳入的第三個引數建立UIApplication物件
2.根據傳入的第四個產生建立UIApplication物件的代理
3.設定剛剛建立出來的代理物件為UIApplication的代理
4.開啟一個事件迴圈
*/
return UIApplicationMain(argc, argv, @"UIApplication", @"YYAppDelegate");
}
}
3.2 系統入口的程式碼和引數說明:
argc:系統或者使用者傳入的引數
argv:系統或使用者傳入的實際引數
1.根據傳入的第三個引數,建立UIApplication物件
2.根據傳入的第四個產生建立UIApplication物件的代理
3.設定剛剛建立出來的代理物件為UIApplication的代理
4.開啟一個事件迴圈(可以理解為裡面是一個死迴圈)這個時間迴圈是一個佇列(先進先出)先新增進去的先處理
3.3 ios程式啟動原理
四、程式啟動的完整過程
1.main函式
2.UIApplicationMain
- 建立UIApplication物件
- 建立UIApplication的delegate物件
3.delegate物件開始處理(監聽)系統事件(沒有storyboard)
- 程式啟動完畢的時候, 就會呼叫代理的application:didFinishLaunchingWithOptions:方法
- 在application:didFinishLaunchingWithOptions:中建立UIWindow
- 建立和設定UIWindow的rootViewController
- 顯示視窗
3.根據Info.plist獲得最主要storyboard的檔名,載入最主要的storyboard(有storyboard)
- 建立UIWindow
- 建立和設定UIWindow的rootViewController
- 顯示視窗
相關文章
- springboot自動配置原理和啟動流程Spring Boot
- SpringBoot啟動原理Spring Boot
- SpringBoot 啟動原理Spring Boot
- springBoot-啟動原理Spring Boot
- Spring容器系列-啟動原理Spring
- SpringBoot 啟動類的原理Spring Boot
- 執行緒啟動原理執行緒
- Tomcat 7 啟動分析(五)Lifecycle 機制和實現原理Tomcat
- SpringBoot啟動流程分析原理(一)Spring Boot
- springboot之啟動原理解析Spring Boot
- Flutter 啟動頁(閃屏頁)具體實現和原理分析Flutter
- 如何手動重啟 Node.js 和用守護程式自動重啟Node.js
- SpringBoot啟動程式碼和自動裝配原始碼分析Spring Boot原始碼
- nacos原理三-註冊中心原理&原始碼啟動.md原始碼
- Linux中如何啟動程式?啟動程式的方法是什麼?Linux
- linux下啟動和終止JAVA程式shell指令碼LinuxJava指令碼
- Swoole 啟動一個服務,開啟了哪些程式和執行緒?執行緒
- springboot系列文章之啟動原理詳解Spring Boot
- SpringBoot 使用外部Tomcat方法及啟動原理Spring BootTomcat
- Android Service重啟恢復(Service程式重啟)原理解析Android
- Android效能優化之啟動過程(冷啟動和熱啟動)Android優化
- centos 自動啟動指令碼和自啟動服務CentOS指令碼
- [譯] 如何手動啟動 Angular 程式Angular
- Arthas原理系列(三):服務端啟動流程服務端
- kill 已啟動的程式
- win10快速啟動有什麼作用_win10快速啟動的原理Win10
- Dart 非同步程式設計和原理Dart非同步程式設計
- 3 啟動和關閉
- 啟動和停止任務
- 怎麼啟動 VIM?14 個 VIM 啟動引數和啟動方法詳解
- 簡述grub啟動載入程式和製作kickstart檔案
- vue 執行程式碼自動啟動Vue行程
- 【SpringBoot】服務 Jar 包的啟動過程原理Spring BootJAR
- 十二、Spring Boot 嵌入式 Servlet 容器啟動原理Spring BootServlet
- 【IDL〕編寫程式啟動介面
- Windows開機啟動指定程式Windows
- Android開機自啟動程式Android
- framework——應用程式啟動流程Framework