IOS/Swift

[Swift] Main Attribute

민몬+ 2021. 10. 8. 03:03

 

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은 따로 종료버튼이 없기 때문에 실행되고 나면 함수가 종료되면 안 되기 때문이다.)

함수 기능

UIApplicataionMain 함수 동작 Flow

  • 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 함수를 제공해야 한다.
    아래 두 가지 방식으로 요구사항을 충족할 수 있다.
    1. Parameter가 없고  Void를 Return 하는 main 함수를 @main Attribute로 지정된 Type 내에 선언
      @main
      struct TestApp {
      	static func main() {
      		// Top-level code goes here
      	}
      }
    2. 아래와 같은 형식의 main 함수를 Protocol에 선언하고 해당 Protocol을 준수
      protocol ProvidesMain {
          static func main() throws
      }

정리하면, @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://docs.swift.org/swift-book/ReferenceManual/Attributes.html#//apple_ref/doc/uid/TP40014097-CH35-ID347

 

Attributes — The Swift Programming Language (Swift 5.5)

Attributes There are two kinds of attributes in Swift—those that apply to declarations and those that apply to types. An attribute provides additional information about the declaration or type. For example, the discardableResult attribute on a function d

docs.swift.org

https://medium.com/@venki0119/role-of-uiapplicationmain-in-ios-app-launch-process-77a00b44ac9d

 

Role of UIApplicationMain in iOS App Launch Process.

This article talks about how the UIApplicationMain method contributes to the iOS App launch process.

medium.com

https://barosalki.tistory.com/entry/iOS-Swift-53-main-type기반의-프로그램-진입점

 

[iOS & Swift 5.3+] @main : type기반의 프로그램 진입점

iOS 프로젝트를 처음 생성하면 자동으로 생성되는 몇 가지 파일이 있죠? 그 중에서 "AppDelegate.swift"는 AppDegate 클래스를 정의하고 앱이 시작되는 진입점을 알려주고 앱의 입력이벤트를 전달하는

barosalki.tistory.com

 

'IOS > Swift' 카테고리의 다른 글

[Swift] Top-Level Code란?  (0) 2021.10.07
[Swift] Entry Point란?  (0) 2021.10.05