Entry Point 포스팅을 통해 설명했듯이
@main, @UIApplicationMain 등의 Attribute를 통해 Entry Point를 지정할 수 있다.
이 포스팅은 각 Attribute가 어떻게 Entry Point를 지정하는지에 대해 설명한다.
@UIApplicationMain
Xcode에서 App 프로젝트를 생성하면 자동으로 생성되는 AppDelegate 파일에서 아래와 같은 코드를 확인할 수 있다.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
... 생략 ...
공식 문서를 통해 @UIApplicationMain Attribute에 대해 알아보자.
Using this attribute is equivalent to calling the UIApplicationMain function and passing this class’s name as the name of the delegate class.
위 문구와 같이 @UIApplicationMain Attribute가 하는 일은 UIApplicationMain 함수를 호출하고
@UIApplicationMain Attribute 아래에 선언된 Class의 이름을 Parameter를 통해 넘겨주는 것이다.
또한 공식 문서는 @UIApplicationMain Attribute를 통해 Entry Point를 지정할 수 있다고 설명한다.
실제로 Xcode 프로젝트에서 @UIApplicationMain Attribute를 삭제할 경우 아래와 같은 메시지를 마주할 수 있다.
Entry Point 포스팅에서 보았던 EntryPoint가 지정되지 않았을 때 발생하는 Error이다.
main.swift 파일을 생성하여 Entry Point를 지정하고 UIApplicationMain 함수를 호출하면 App이 실행됨을 확인할 수 있다.
정리하면 @UIApplicationMain Attribute는 아래의 코드를 대신한다고 할 수 있다.
func main(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>) -> Int32 {
return UIApplicationMain(argc, argv, nil, "AppDelegate")
}
UIApplicationMain(_:_:_:_:)
@UIApplicationMain Attribute를 통해 호출하는 UIApplicationMain(_:_:_:_:) 함수는 무슨역할을 할까?
공식문서를 참조하여 UIApplicationMain 함수에 대해 알아보자.
func UIApplicationMain(_ argc: Int32,
_ argv: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>,
_ principalClassName: String?,
_ delegateClassName: String?) -> Int32
함수 구조
- argc
argv Parameter의 개수, 일반적으로 main 함수의 Parameter와 동일하다. - argv
변수의 목록이다. 일반적으로 main 함수의 Parameter와 동일하다. - principalClassName
UIApplication Class 혹은 subClass의 이름이다. nil로 지정할 경우 "UIApplication"으로 전달된다. - delegateClassName
UIApplication의 Delegate 객체로 지정될 Class의 이름이다. (UIApplicationDelegate Protocol 구현)
nil을 지정할 경우 Info.plist file에 지정된 main.nib file로부터 delegate를 지정한다. - Return Value
Return Type이 선언되어 있지만 이 함수는 Return하지 않는다.
(App은 따로 종료버튼이 없기 때문에 실행되고 나면 함수가 종료되면 안 되기 때문이다.)
함수 기능
- principaClassName을 통해 전달받은 이름의 Application(UIApplication) 객체를 초기화한다.
- delegateClassName을 통해 전달받은 delegate Class를 객체화한다.
- Info.plist file에서 NSMainNibFile Key를 포함하여 main.nib file이 지정된 경우 Main StoryBoard를 Load 한다.
- Application의 run loop을 포함하는 main event loop을 셋업하고 Event 처리를 시작한다.
정리하면 UIApplicationMain(_:_:_:_:) 함수는
UIApplication 객체를 생성하고 UIApplicataion의 Delegate 객체를 지정하여 App을 Control 한다.
@main
Swift 5.3부터는 @main Attribute를 제공한다.
@UIApplicationMain Attribute가 생기고 수년 후 UIKit은 더 이상 유일한 Framework가 아니게 되었다. Ex) Swift UI
따라서 @UIApplicationMain Attribute 외의 Entry Point를 지정할 수 있는 더욱 추상화된 방법이 필요했다.
@main은 UIKit 이외의 Framework에서도 동작할 수 있는 추상화된 Entry Point를 제공한다.
공식문서에서 설명하는 @main의 특징은 아래와 같다.
- @main Attribute는 Structure, Class, Enumeration 모두에 적용할 수 있다.
(@UIApplicationMain Attribute는 Class만 적용 가능) - @main Attribute를 사용하기 위해서는 반드시 main 함수를 제공해야 한다.
아래 두 가지 방식으로 요구사항을 충족할 수 있다.- Parameter가 없고 Void를 Return 하는 main 함수를 @main Attribute로 지정된 Type 내에 선언
@main struct TestApp { static func main() { // Top-level code goes here } }
- 아래와 같은 형식의 main 함수를 Protocol에 선언하고 해당 Protocol을 준수
protocol ProvidesMain { static func main() throws }
- Parameter가 없고 Void를 Return 하는 main 함수를 @main Attribute로 지정된 Type 내에 선언
정리하면, @main은 Protocol의 동작과 같이 해당 Type이 main함수를 갖게 강제하여 Entry Point를 제공한다.
아래는 앱을 시작하기 위해 UIApplicationMain(_:_:_:_:) 함수를 호출하는 방법을 @main Attribute의 방식으로 변형한 예시이다.
아래와 같이 @main Attribute를 사용하면 링커는 TestApp의 main함수를 Entry Point로 지정한다.
@main
struct TestApp {
static func main() {
UIApplicationMain(argc, argv, nil, "AppDelegate")
}
}
Reference
https://medium.com/@venki0119/role-of-uiapplicationmain-in-ios-app-launch-process-77a00b44ac9d
https://barosalki.tistory.com/entry/iOS-Swift-53-main-type기반의-프로그램-진입점
'IOS > Swift' 카테고리의 다른 글
[Swift] Top-Level Code란? (0) | 2021.10.07 |
---|---|
[Swift] Entry Point란? (0) | 2021.10.05 |