最近看視頻瞭解了一下應用程式的啟動原理,這裡就做一個博客和大家分享一下,相互討論,如果有什麼補充或不同的意見可以提出來! 1、程式入口 眾所周知,一個應用程式的入口一般是一個 main 函數,iOS也不例外,在工程的 Supporting Files 文件夾中你可以找到main.m,他就是程式的入口 ...
最近看視頻瞭解了一下應用程式的啟動原理,這裡就做一個博客和大家分享一下,相互討論,如果有什麼補充或不同的意見可以提出來!
1、程式入口
眾所周知,一個應用程式的入口一般是一個 main 函數,iOS也不例外,在工程的 Supporting Files 文件夾中你可以找到main.m,他就是程式的入口。
代碼:
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class])); } }
2、UIApplicationMain函數參數解析
UIApplicationMain 函數的聲明:
// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no // NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init. int UIApplicationMain(int argc, char *argv[], NSString * __nullable principalClassName, NSString * __nullable delegateClassName);
-
第一個參數 argc 和 第二個參數 argv 為C語言的值,在這裡可以不做考慮。
-
第三個參數 principalClassName:主程式類名,由英文註釋可知,當值為 nil 時,預設使用的就是 UIApplication
-
第四個參數:delegateClassName:代理類名,在 iOS 中預設就是隨工程一起創建出來的AppDelegate。
第四個參數的類型是一個字元串,但是在主函數卻是 NSStringFromClass([AppDelegate class]) 。NSStringFromClass() 函數是將一個類名轉為字元串的一種特殊轉換函數,[AppDelegate class] 則是反射得到AppDelegate 對象的類名。
和 NSStringFromClass() 函數類似的一系列函數聲明:
FOUNDATION_EXPORTNSString *NSStringFromSelector(SEL aSelector); // 函數名轉字元串 FOUNDATION_EXPORT SEL NSSelectorFromString(NSString *aSelectorName); // 字元串轉函數名 FOUNDATION_EXPORT NSString *NSStringFromClass(Class aClass); // 類名轉字元串 FOUNDATION_EXPORT Class __nullable NSClassFromString(NSString *aClassName); // 字元串轉類名 FOUNDATION_EXPORT NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0); // 協議名轉字元串 FOUNDATION_EXPORT Protocol * __nullable NSProtocolFromString(NSString *namestr) NS_AVAILABLE(10_5, 2_0); // 字元串轉協議名
3、UIApplicationMain底層實現
(1)根據 principalClassName 提供類名創建 UIApplication 對象
(2)創建 UIApplicationDelegate 對象,並且成為 UIApplication 對象代理,app.delete = delegate
(3)開啟一個主運行迴圈,處理事件,可以保持程式一直運行。
(4)載入 info.plist,並且判斷 Main Interface 有木有指定 main.storyboard,如果指定,就會去載入
(5)如果有指定,載入 main.stroyboard 做的事情
創建視窗,也就會說執行 AppDelegate 中的代理方法
載入 main.storyboard, 並且載入 main.storyboard 指定的控制器
把新創建的控制器作為視窗的跟控制器,讓視窗顯示出來
(6)如果沒有指定,就在 AppDelegate 的代理方法 - (BOOL)application: didFinishLaunchingWithOptions:中創建一個UIWindow 對象作為主視窗
代碼:
// 程式啟動完成的時候 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. // 1.創建視窗,註意視窗必須要有尺寸,尺寸跟屏幕一樣大的尺寸,視窗不要被釋放 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor redColor]; // 2.創建視窗的根控制器 UIViewController *vc = [[UIViewController alloc] init]; vc.view.backgroundColor = [UIColor yellowColor]; [vc.view addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]]; // 如果設置視窗的跟控制器,預設就會把控制器的view添加到視窗上 // 設置視窗的跟控制器,預設就有旋轉功能 self.window.rootViewController = vc; // 3.顯示視窗 [self.window makeKeyAndVisible]; return YES; }
圖解:
官方幫助文檔圖解: