iOS -程序啓動原理和UIApplication的介紹

一.UIApplication 簡介
     
(1)UIApplication對象是應用程序的象徵,一個UIApplication對象就表明一個應用程序。
(2)每個Application都有本身的UIApplication對象,並且是單例的,若是用試圖再去實例化一個UIApplication則會報錯: [ [ UIApplication alloc ]  init ];
(3)經過[UIApplication sharedApplication]能夠得到這個單例對象。
(4) 一個iOS程序啓動後建立的第一個對象就是UIApplication對象,且只有一個(可經過代碼獲取兩個UIApplication對象,打印地址相同)。
(5)利用UIApplication對象,能進行一些應用級別的操做。

二.應用級別的操做舉例
1)設置應用程序圖標右上角的紅色提醒數字(如QQ消息的時候,圖標上面會顯示1,2,3條新信息等。)
@property ( nonatomic ) NSInteger applicationIconBadgeNumber __TVOS_PROHIBITED
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}
//點擊屏幕會調用該方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UIApplication *app = [UIApplication sharedApplication];
    //註冊通知
    UIUserNotificationSettings *nitice = [UIUserNotificationSettings
    settingsForTypes:UIUserNotificationTypeBadge categories:nil];
    
    [app registerUserNotificationSettings:nitice];
    //IconBadgeNumber
    app.applicationIconBadgeNumber = 20;
}
@end

運行效果:


2)設置聯網指示器的可見性
@property ( nonatomic , getter =isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible __TVOS_PROHIBITED ;
代碼: app. networkActivityIndicatorVisible = YES ;
運行效果:


3)管理狀態欄
從iOS7開始,系統提供了2種管理狀態欄的方式
a.經過UIViewController管理(每個UIViewController均可以擁有本身不一樣的狀態欄).
在iOS7中,默認狀況下,狀態欄都是由UIViewController管理的,UIViewController實現下列方法就能夠輕鬆管理狀態欄的可見性和樣式
狀態欄的樣式     - (UIStatusBarStyle)preferredStatusBarStyle; 
狀態欄的可見性  -(BOOL)prefersStatusBarHidden;
代碼:
#pragma mark - 狀態欄的樣式
- (UIStatusBarStyle)preferredStatusBarStyle {

    return  UIStatusBarStyleLightContent;
}
#pragma mark - 是否隱藏狀態欄(no)
- (BOOL)prefersStatusBarHidden {
    return NO;
}


b.經過UIApplication管理(一個應用程序的狀態欄都由它統一管理)
若是想利用UIApplication來管理狀態欄,首先得修改Info.plist的設置


代碼:
 
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //獲取
    UIApplication *app = [UIApplication sharedApplication];
    //註冊通知
    UIUserNotificationSettings *nitice =
    [UIUserNotificationSettings          settingsForTypes:UIUserNotificationTypeBadge categories:nil];
    [app registerUserNotificationSettings:nitice];
    //IconBadgeNumber
    app.applicationIconBadgeNumber = 20;
    app.networkActivityIndicatorVisible = YES;
     //設置狀態欄
    app.statusBarHidden = NO;
    app.statusBarStyle = UIStatusBarStyleDefault;
}


注意:既然兩種均可以對狀態欄進行管理,那麼何時該用什麼呢?
          若是狀態欄的樣式只設置一次,那就用UIApplication來進行管理;
          若是狀態欄是否隱藏,樣式不同那就用控制器進行管理。
 4)openURL:方法

UIApplication有個功能十分強大的openURL:方法
- ( BOOL )openURL:( NSURL *)url
openURL:方法的部分功能有
打電話   
[app openURL:[NSURLURLWithString:@"tel://10010"]];
發短信 
[app openURL:[NSURLURLWithString:@"sms://10010"]];
發郵件 
[app openURL:[NSURLURLWithString:@"mailto://xxxxxx@qq.com"]];
打開一個網頁資源 
[app openURL :[[ NSURL  alloc ] initWithString : @"http://baidu.com" ]];

打開其餘app程序   openURL方法,能夠打開其餘APP。網絡

  URL
     URL:統一資源定位符,用來惟一的表示一個資源。 
     URL格式: 協議頭://主機地址/資源路徑
     網絡資源:http/ ftp等   表示百度地址: http://baidu.com
     本地資源:file:///users/apple/desktop/abc.png(主機地址省略)

三. UIApplication Delegate

     爲何會UIApplication Delegate?
     移動操做系統都有個致命的缺點:app容易受到打擾。好比電話或者鎖屏會致使app進入後臺甚至被終止。此時app會產生一些系統事件,UIApplication會通知它的delegate對象,讓delegate代理來處理這些系統事件。
     總結: AppDelegate 的主要做用就是處理 ( 監聽 ) 應用程序自己的各類事件
          應用程序啓動完畢
           應用程序進入後臺
          應用程序進入前臺
          等,應用程序自身的一些事件  
        
  要想成爲 UIApplication 的代理對象 , 必須遵照 :UIApplicationDelegate 協議每次建立新項目,Xcode會幫我生成一個「AppDelegate」的類,它就是代理,而且該類已經默認遵循了UIApplicationDelegate的代理,且成爲了代理(在程序啓動部分會有更多解釋)。




UIApplication的代理協議有許多,AppDelegate這個類默認遵循了 < UIApplicationDelegate > ,並且實現了部分代理方法,從而監控咱們的應用程序。
UIApplication的代理屬性:
@property ( nullable , nonatomic , assign ) id < UIApplicationDelegate > delegate;

實現的代理方法在 AppDelegate.m中 以下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // 當應用程序啓動完畢的時候就會調用(系統自動調用)
    NSLog(@"%s",__func__);
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // 即將失去活動狀態的時候調用
     NSLog(@"%s",__func__);
}

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

    // 應用程序進入後臺的時候調用
     NSLog(@"%s",__func__);
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
          / / 應用程序即將進入前臺的時候調用
     NSLog(@"%s",__func__);
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
      // 從新激活(可以和用戶交互)
     NSLog(@"%s",__func__);
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // 應用程序即將被銷燬的時候會調用該方法
     NSLog(@"%s",__func__);
}

應用程序通常有五個狀態:官方文檔app.states



4、程序啓動原理

1.先簡單回顧一下,咱們最經典的應用程序hello world:
它告訴咱們,應用程序的入口是main函數;
#include<stdio.h>
int main(int argc,char* argv[])
{
    printf("hello, world\n");
    return 0;
}

2.再看一段Linux下的qt的一個應用程序:     
它的程序入口也是main函數,且 app.exec();將應用程序的控制權傳遞給 Qt
,進入事件循環的狀態,等待用戶操做。

#include <QtGui>
int main(int argc,char *argv[]) {
    QApplication app(argc,argv);
    QLabel label(QString("hellow qt"));
    label.show();
    app.exec();
}

3. 由此,能夠猜想iOS的程序的入口也是main函數,最終程序也會進入一個事件的循環,等待用戶操做,監控;
在iOS的main.m,找到了程序的入口main函數,該函數只有一句;
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

即:main函數中調用了 UIApplicationMain方法
int UIApplicationMain( int argc, char *argv[], NSString * __nullable principalClassName, NSString * __nullable delegateClassName);
  • argcargc是命令行總的參數個數
  • argvargv[]是argh個參數,記錄用戶輸入的參數;
  • principalClassName指定應用程序類名(app的象徵),該類必須是UIApplication(或子類),若是爲nil則用UIApplication類做爲默認值
  • delegateClassName指定應用程序的代理類UIApplicationDelegate協議中定義的方法,在該類中實現
     UIApplicationMain函數會根據principalClassName建立UIApplication對象,根據delegateClassName建立一個delegate對象,並將該delegate對象賦值給UIApplication對象中的delegate屬性,接着會創建應用程序的Main Runloop(事件循環),進行事件的處理(首先會在程序完畢後調用delegate對象的application:didFinishLaunchingWithOptions:方法程序正常退出時UIApplicationMain函數才返回。
    
      總結:UIApplicationMain就是讓咱們的應用程序和代理之間創建聯繫,而後進入Runloop,進行事件處理;咱們直接給UIApplicationMain傳遞應用程序的類名和代理的類名也是同樣的。
即: return   UIApplicationMain (argc, argv, @"UIApplication" , @"AppDelegate" );

4.程序啓動的完整過程:


1.main函數
     UIApplicationMain
     * 建立UIApplication對象
     * 建立UIApplication的delegate對象
2.delegate對象開始處理(監聽)系統事件
     2.1沒有storyboard
     * 程序啓動完畢的時候, 就會調用代理的application:didFinishLaunchingWithOptions:方法
     * 在application:didFinishLaunchingWithOptions:中建立UIWindow
     * 建立和設置UIWindow的rootViewController
     * 顯示窗口
代碼:
#import "AppDelegate.h"
#import "ViewController.h"

      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    ViewController *vc = [[ViewController alloc] init];
    self.window.rootViewController = vc;
    vc.view.backgroundColor = [UIColor redColor];
    [self.window makeKeyAndVisible];
    return YES;
}

     2.2. (有storyboard)
     根據Info.plist得到最主要storyboard的文件名,加載最主要的storyboard
     * 建立UIWindow
     * 建立和設置UIWindow的rootViewController
     * 顯示窗口 
相關文章
相關標籤/搜索