swift 中的 @UIApplicationMain

Inlight發表於2017-12-25

程式如何開始的

C 系列語言中,程式的入口都是 main 函式,一個 Objective-C 的 iOS app 專案在新建時,Xcode 會給我們建立好一個 main.m 的檔案。

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}
複製程式碼

我們呼叫了 UIKit 的 UIApplicationMain 方法,這個方法根據第三個引數初始化一個 UIApplication 或者它的子類物件開始接收事件。當傳入 nil 時則使用預設的 UIApplication。最後一個引數指定了 AppDelegate 類作為應用的委託,用來接收與應用生命週期相關的委託方法。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
}

- (void)applicationWillResignActive:(UIApplication *)application {
}

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

- (void)applicationWillEnterForeground:(UIApplication *)application {
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
}

- (void)applicationWillTerminate:(UIApplication *)application {
}
複製程式碼

雖然這個方法標明要返回一個 int,但其實它並不會真正的返回,而是一直存在於記憶體中,直到使用者或者系統將應用強制終止。

swift 中的對應情況

建立一個 swift 的專案之後,我們發現所有的檔案中並沒有一個類似於 Objective-C 中的 main.m 檔案,也沒有 main 函式。唯一和 main 有關係的就是在 AppDelegate 中有一個 @UIApplicationMain 標籤。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

}
複製程式碼

這個標籤的作用就是將標註的類作為委託,建立一個 UIApplication 並啟動整個程式。一般情況我們不需要對這個標籤做任何修改,但如果我們想使用 UIApplication 的子類而不是它本身,我們就要自定義一個 main.swift 檔案了(記得刪除 @UIApplicationMain 標籤)。這個檔案我們不需要定義作用域,直接寫程式碼就OK。

import UIKit

class MyApplication: UIApplication {
    override func sendEvent(_ event: UIEvent) {
        super.sendEvent(event)
        print("Event sent:\(event)")
    }
}

UIApplicationMain(
    CommandLine.argc,
    UnsafeMutableRawPointer(CommandLine.unsafeArgv)
        .bindMemory(
            to: UnsafeMutablePointer<Int8>.self,
            capacity: Int(CommandLine.argc)),
    NSStringFromClass(MyApplication.self),
    NSStringFromClass(AppDelegate.self)
)
複製程式碼

這樣每次傳送事件(點選按鈕之類的)我們都可以監聽到了。

相關連結

相關文章