오늘은 SwiftUI 프로젝트를 생성했을 때 생성되는 기본 템플릿 코드에 대해서 분석해보도록 하겠습니다.
import SwiftUI
@main
struct ExSwiftUIApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
// modifier를 사용해서 View의 속성값 조절
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SwiftUI 프로젝트를 생성하면 기본적으로 위와 같은 struct로 구현되어 있는 기본 템플릿 코드가 생성됩니다.
위에서부터 차근차근 살펴보겠습니다
@main
SwiftUI 앱의 Entry Point(진입점)을 나타내기 위해 App에 @main 속성을 적용합니다.
Entry Point는 1개만 존재해야합니다. 2개 이상 있다면 컴파일 에러가 발생합니다.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
UIKit은 위와 같이 앱의 Entry Point가 AppDelegate에 @main 속성으로 정의되어 있었죠?
SwiftUI에서는 AppDelegate, SceneDelegate가 따로 없으며, App 프로토콜을 채택하는 구조체에 @main 속성을 적용하여 앱의 Entry Point를 지정합니다.
struct ExSwiftUIApp: App { ... }
앱을 생성하기 위해 App 프로토콜을 준수하는 구조체를 선언합니다.
App은 앱의 구조와 동작을 나타내는 유형입니다.
var body: some Scene { ... }
앱의 콘텐츠를 정의하는데 필요한 Computed property인 body를 구현합니다.
body는 Scene 프로토콜을 준수합니다. 이때, some 키워드를 사용해 body의 구체적인 타입을 숨기고, 단순하게 Scene 타입을 준수하는 어떠한 타입으로 만듦으로써 뷰의 복잡성을 감추고, 생상성을 높일 수 있습니다.
각 Scene은 뷰 계층 구조의 루트 뷰를 포함하며 시스템에서 관리하는 수명주기를 갖습니다.
SwiftUI에서 Scene은 WindowGroup, Window, DocumentGroup, Settings 등 다양한 유형의 Scene을 제공합니다.
WindowGroup {
ContentView()
}
멀티 윈도우를 지원하는 앱의 주요 인터페이스를 선언하기 위해 WindowGroup을 사용하고, 앱의 콘텐츠를 포함하고 있는 뷰 계층 구조를 만드는 사용자 지정 뷰인 ContentView를 포함합니다.
SwiftUI에서 Scene에는 UI로 표시하는 뷰 계층 구조가 포함됩니다.
뷰 계층 구조는 다른 뷰를 기준으로 뷰의 레이아웃을 정의합니다.
struct ContentView: View { ... }
ContentView는 View 프로토콜을 준수하는 구조체입니다.
View는 화면의 시각적인 요소를 정의하고 일반적으로 다른 뷰들로 구성되어 뷰 계층 구조를 만듭니다.
var body: some View { ... }
콘텐츠를 정의하기 위해 View 프로토콜을 따르는 computed property인 body를 구현합니다.
마찬가지로 some 키워드를 사용해서 body의 구체적인 타입을 감춰 복잡성을 낮춥니다.
코드의 패턴을 보면, ExSwiftUIApp에 있는 App, Scene 프로토콜을 준수하는 코드의 패턴과 동일합니다. 이러한 패턴은 SwiftUI 코드에서 볼 수 있는 일반적인 패턴입니다.
VStack {
Image(systemName: "globe")
// view modifier를 사용해 view의 속성값 조절
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
VStack을 사용해서 블럭 내부의 모든 하위 뷰를 세로로 정렬할 수 있습니다.
하위 뷰가 많지 않고 세로로 정렬하고 싶을 때 VStack을 사용하는 것이 이상적이지만,
많은 하위 뷰를 포함하는 경우 LazyVStack을 사용하는 것이 좋습니다.
ScrollView {
LazyVStack {
ForEach(1...300, id: \.self) {
Text("Row \($0)")
}
}
}
LazyVStack은 필요할 때까지 뷰의 인스턴스를 생성하지 않는 Lazy(게으른)VStack입니다.
많은 양의 데이터를 처리해야 할 때 모든 데이터 항목에 대한 뷰를 한번에 로드하면, 앱의 성능 문제를 야기할 수 있습니다.
LazyVStack을 사용하면, 현재 화면에 보이는 항목들만 로드되므로 메모리 사용량을 크게 줄일 수 있습니다.
출처 : https://developer.apple.com/tutorials/swiftui-concepts/exploring-the-structure-of-a-swiftui-app