Swift中main函式去哪了?

weixin_34402408發表於2018-04-03

這篇文章我是基於Swift 3下寫的,有些東西,可能會跟之前版本有些出入,不過影響不大

從我們一開始學C語言的時候,就知道main()函式是一個程式的entry point,這是約定俗成的東西,當然,iOS APP 也不例外。

之前我們用Xcode新建一個專案,選擇Objective-C作為開發語言,建成的工程裡面除了AppDelegate.mMain.storyboard等再熟悉不過的檔案,還有一個main.m,既熟悉又陌生。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        MCSLog(@"%s", argv[0]);
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

同樣的,這也是我們一個iOS 程式的入口,呼叫UIApplicationMain函式註冊了Application代理,開始了事件迴圈。

不過,當我們新建一個Swift工程的時候,細心的同學就會發現,找不到我們熟悉的main.swift檔案了,同時我們也會在AppDelegate.swift裡,發現一個@UIApplicationMainAttribute。
官方文件這麼描述的:

UIApplicationMain
Apply this attribute to a class to indicate that it’s the application delegate. 
Using this attribute is equivalent to calling the UIApplicationMain function and passing this class’s name as the name of the delegate class.

還有Stack上的回答也很詳細,建議看看。

原來,@UIApplicationMain就是為了取代我們在OC專案中的main.m,它實現了main函式(程式入口)以及呼叫了Cocoa Touch上的UIApplicationMain 函式,開啟事件迴圈。

應用了這個 UIApplicationMain Attribute也就表明,當前類作為application的代理,也就等同於這個函式的呼叫UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
因此,你也可以簡單認為,AppDelegate.swiftmain.swift通過這個Attribute合併為一體了,AppDelegate.swift也成為initial entry file.

那麼,你自己新建MyAppDelegate.swift,然後Apply @UIApplicationMain,同樣也是可以的

// 使用@UIApplicationMain,必須要遵循UIApplicationDelegate,不然編譯器會報如下錯誤
// 'UIApplicationMain' class must conform to the 'UIApplicationDelegate' protocol
@UIApplicationMain
class MyAppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
}

到這裡,可能有些同學就會問,那我自己建個main.swift檔案呢?當然可以!
新建一個main.swift,這裡注意一點,檔名稱必須是main.swift, 然後實現如下:

import UIKit
import Foundation

// Swift 2 使用Process.argc
let argc = CommandLine.argc // Swift 3 把 Process改為CommandLine 了
let argv = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.allocate(capacity: Int(CommandLine.argc))
// let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))
UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.self))

這裡注意一點:如果你自己建立了main.swift,那麼記得把@UIApplicationMain去掉,不然會報錯
'UIApplicationMain' attribute cannot be used in a module that contains top-level code

@UIApplicationMain 只是在iOS上,Mac OS上相應的是@NSApplicationMain

相關文章