標籤:
iOS中的應用啟動原理來源: http://m.warting.com/program/201601/127355.html
一、UIApplication
1. 簡單介紹
(1)UIApplication對象是應用程式的象徵,一個UIApplication對象就代表一個應用程式。
(2)每一個應用都有自己的UIApplication對象,而且是單例的,如果試圖在程式中建立一個UIApplication對象,那麼將報錯提示。
(3)通過[UIApplicationsharedApplication]可以獲得這個單例對象
(4) 一個iOS程式啟動後建立的第一個對象就是UIApplication對象,且只有一個(通過代碼擷取兩個UIApplication對象,列印地址可以看出地址是相同的)。
(5)利用UIApplication對象,能進行一些應用層級的操作
2.應用層級的操作樣本:(1)設定應用程式圖示右上方的紅色提醒數字(如QQ訊息的時候,表徵圖上面會顯示1,2,3條新資訊等。)
代碼如下:
@property(nonatomic) NSInteger applicationIconBadgeNumber;
代碼實現和效果:
- (void)viewDidLoad
{
[super viewDidLoad];
// UIApplication *app=[[UIApplication alloc]init]; //錯誤,只能有一個唯一的UIApplication對象,不能再進行建立
UIApplication *app=[UIApplication sharedApplication]; //通過sharedApplication擷取該程式的UIApplication對象
app.applicationIconBadgeNumber=123;
}
(2)設定連網指標的可見度
代碼如下:
@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible;
代碼和效果: //設定指標的連網動畫
app.networkActivityIndicatorVisible=YES;
(3)管理狀態列
a. 通過UIViewController管理(每一個UIViewController都可以擁有自己不同的狀態列)
從iOS7開始,系統提供了2種管理狀態列的方式,預設情況下,狀態列都是由UIViewController管理的,UIViewController實現下列方法就可以輕鬆管理狀態列的可見度和樣式。
代碼如下:#pragma mark-設定狀態列的樣式
-(UIStatusBarStyle)preferredStatusBarStyle
{
//設定為白色
//return UIStatusBarStyleLightContent;
//預設為黑色
return UIStatusBarStyleDefault;
}
#pragma mark-設定狀態列是否隱藏(否)
-(BOOL)prefersStatusBarHidden
{
return NO;
} b. 通過UIApplication管理(一個應用程式的狀態列都由它統一管理)
如果想利用UIApplication來管理狀態列,首先得修改Info.plist的設定,
代碼如下:
//通過sharedApplication擷取該程式的UIApplication對象 UIApplication *app=[UIApplication sharedApplication];
//設定狀態列的樣式
//app.statusBarStyle=UIStatusBarStyleDefault;//預設(黑色)
//設定為白色+動畫效果
[app setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
//設定狀態列是否隱藏
app.statusBarHidden=YES;
//設定狀態列是否隱藏+動畫效果
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
c. 既然兩種都可以對狀態列進行管理,那麼什麼時候該用什麼呢?
如果狀態列的樣式只設定一次,那就用UIApplication來進行管理;
如果狀態列是否隱藏,樣式不一樣那就用控制器進行管理。
UIApplication來進行管理有額外的好處,可以提供動畫效果。
(4)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://[email protected]"]];
開啟一個網頁資源 代碼如下:
[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.代理方法
代碼如下:
#import "YYAppDelegate.h"
@implementation YYAppDelegate
// 當應用程式啟動完畢的時候就會調用(系統自動調用)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"didFinishLaunchingWithOptions");
return YES;
}
// 即將失去活動狀態的時候調用(失去焦點, 不可互動)
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"ResignActive");
}
// 重新擷取焦點(能夠和使用者互動)
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"BecomeActive");
}
// 應用程式進入背景時候調用
// 一般在該方法中儲存應用程式的資料, 以及狀態
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"Background");
}
// 應用程式即將進入前台的時候調用
// 一般在該方法中恢複應用程式的資料,以及狀態
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"Foreground");
}
// 應用程式即將被銷毀的時候會調用該方法
// 注意:如果應用程式處於掛起狀態的時候無法調用該方法
- (void)applicationWillTerminate:(UIApplication *)application
{
}
// 應用程式接收到記憶體警告的時候就會調用
// 一般在該方法中釋放掉不需要的記憶體
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
NSLog(@"MemoryWarning");
}
@end
三、UIApplicationMain
1. main函數中執行了一個UIApplicationMain這個函數
intUIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
argc、argv:直接傳遞給UIApplicationMain進行相關處理即可
principalClassName:指定應用程式類名(app的象徵),該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為預設值
delegateClassName:指定應用程式的代理類,該類必須遵守UIApplicationDelegate協議
UIApplicationMain函數會根據principalClassName建立UIApplication對象,根據delegateClassName建立一個delegate對象,並將該delegate對象賦值給UIApplication對象中的delegate屬性
接著會建立應用程式的Main Runloop(事件迴圈),進行事件的處理(首先會在程式完畢後調用delegate對象的application:didFinishLaunchingWithOptions:方法)
程式正常退出時UIApplicationMain函數才返回。
2. 代碼如下:#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]));
return UIApplicationMain(argc, argv, @"UIApplication", @"YYAppDelegate");
}
}
3. 系統入口的代碼和參數說明:
argc:系統或者使用者傳入的參數
argv:系統或使用者傳入的實際參數
1.根據傳入的第三個參數,建立UIApplication對象
2.根據傳入的第四個產生建立UIApplication對象的代理
3.設定剛剛建立出來的代理對象為UIApplication的代理
4.開啟一個事件迴圈(可以理解為裡面是一個死迴圈)這個時間迴圈是一個隊列(先進先出)先添加進去的先處理
四、程式啟動的完整過程
1. 有storyboard檔案
1. 調用main函數
2. 調用UIApplicationMain函數
3. 建立UIApplication對象 、 AppDelegate對象
4. 設定UIApplicatio對象的代理是AppDelegate對象。
5. AppDelegate對象開始監聽”系統事件(應用程式的事件)”,進入”事件迴圈”
6. 程式啟動完畢後調用 application: didFinishLaunchingWithOptions:方法。
7. 在application: didFinishLaunchingWithOptions:方法中自動建立
* UIWindow對象。
* 根據Info.plist檔案配置(Main Interface),找到需要載入的storyboard檔案(Main.storyboard)
* 找到Main.storyboard中的Is Initial View Controller 對應的控制器類, 建立該控制器對象。
* 根據storyboard中的配置, 建立控制器對應的view。
* 設定UIWindow的根控制器(rootViewController)為剛才建立的控制器。
* 顯示UIWindow([self.window makeKeyAndVisible])。
2. 沒有storyboard檔案
1. 調用main函數。
2. 調用UIApplicationMain函數。
3. 建立UIApplication對象 、 AppDelegate對象
4. 設定UIApplicatio對象的代理是AppDelegate對象。
5. AppDelegate對象開始監聽”系統事件(應用程式的事件)”,進入”事件迴圈”。
6. 程式啟動完畢後調用 application: didFinishLaunchingWithOptions:方法。
7. 在application: didFinishLaunchingWithOptions:方法中手動建立:
* UIWindow
* 控制器
* 設定UIWindow的根控制器是剛才建立的控制器
* 顯示UIWindow
3. ios程式啟動原理圖解
4. 四大對象關係圖
iOS中的應用啟動原理