본문 바로가기

도서/SwiftUI by Tutorials

[SwiftUI by Tutorials] Chapter 01, 02: Getting Start

반응형

Chapter 01: Introduction

SwiftUI 특징

  • Apple 개발의 새로운 패러다임
  • UIKit에 비하여 훨씬 간단하고 강력
  • Apple 에코시스템의 크로스 플랫폼
  • 선언적인 특성
  • Swift가 처음 출시 이후로 진화가 필요했던 것처럼, SwiftUI 역시 개선의 여지가 있음

 

+ 추가 내용 (명령형 vs 선언형 프로그래밍)

명령형(절차적) 프로그래밍은 당신이 어떤 일을 어떻게(How) 할 것인가에 관한 것이고,

선언형 프로그래밍은 당신이 무엇을(What) 할 것인가에 관한 것이다.

 

Wal-Mart

친구가 당신의 집에 집들이를 오기 위해 Wal-Mart에서 선물을 샀습니다.

현재 친구는 Wal-Mart 바로 옆에 있으며, 당신의 집에 어떻게 도달해야 하는지를 전화로 물어봅니다.

이에 관한 명령형, 선언형 대답을 다음과 같습니다.

 

  • 명령형 접근(HOW):
    주차장 북쪽 출구로 나와서 좌회전으로 해. 12번가 출구에 도착할 때까지 북쪽 도로를 타고 와야 해. 거기서 IKEA에 가는 것처럼 출구에서 우회전을 해. 그리고 거기서 직진하다가 첫 번째 신호등에서 우회전을 해. 그다음에 나오는 신호등을 통과한 후에 좌회전을 해서 아파트로 들어오면 돼. 우리 집은 101동 100호야

  • 선언형 접근(WHAT):
    우리 집 주소는 서울시 OO구 OO로 OOO, OO아파트 101동 100호야

 

하지만 선언형 방법에서, "주소는 아는데, 집에 가는 방법은 어떻게 알지?"와 같은 의문이 생길 수 있다.

이에 대한 대답은, 선언적 방식으로 접근하기 위해서는 명령형 방식으로 '어떻게 접근하는가'에 대한 내용이 먼저 추상회 되어 있어야 한다는 것이다.

친구에게 우리 집 주소를 알려주는 것도, 친구가 '우리 집에 어떻게 도착할 수 있는가'에 대한 명령적 절차들을 모두 알고 있는 일종의 GPS 같은 것을 가지고 있다는 것을 전제로 한다.

내용은 다음의 문장으로 다시 한번 정리할 수 있다.

선언적(Declarative) 접근의 방식들의 기반에는 일종의 명령적(Imperative) 추상화가 존재한다.

 

 

Chapter 02: Getting Started

Getting Start

SwiftUI App을 생성하면 익숙하게 보던 AppDelegate.swift가 없다.

프로젝트이름App.swift가 이를 대신한다.

 

@main
struct SampleApp: App {
	var body: some Scene {
		WindowGroup {
			ContentView()
		}
	}
}
  • @main 속성은 앱의 진입점이 포함되어 있음을 의미한다.
  • WindowGroup을 만들고, ContentView()로 시작된다
struct ContentView: View {
	var body: some View {
		Text("Hello, world!")
			.padding()
	} 
}
  • ContentView body에 Hello World를 표시하는 Text 뷰가 포함되어 있음을 선언한다.
  • padding() modifier는 텍스트 주위에 10포인트 패딩을 추가한다.

 

Previewing your ContentView

ContentView.swift에서 ContentView 구조체 아래에 ContentView_Previews가 있고, ContentView 인스턴스를 포함하고 있는 것을 볼 수 있다.

 

struct ContentView_Previews : PreviewProvider {
	static var previews: some View {
		ContentView()
	}
}
  • 여기에서 Preview에 대한 샘플 데이터 지정할 수 있다.
  • 다양한 화면 및 font size 등을 비교할 수 있다.

Preview Resume button

  • Resume 버튼 클릭해서 preview를 볼 수 있다.
  • Option-Command-P shortcut으로 할 수 있다.

 

Some SwiftUI vocabulary

  • Modifiers:
    UIKit property, attribute를 직접 설정하는 것 대신, modifier method를 통해 foreground color, font, padding 등의 많은 항목들을 설정할 수 있다.
  • Container views:
    UIKit에서 StackView를 사용해봤다면 HStack, VStack container view를 통해 보다 쉽게 SwiftUI에서 UI를 만들 수 있다. ZStack, Group을 비롯한 다른 container view들도 있다. body는 단일 View를 리턴하는 연산 프로퍼티로, 여러 View를 사용하기 위해 container view를 사용한다.

 

Updating the UI

SwiftUI view 속성 값이 변경될 때, UI가 업데이트되어야 하는 경우 @State 속성으로 지정한다.

SwiftUI에서는@State 값이 변경되면 뷰를 무효화하고 body를 다시 연산한다.

 

Binding

Slider(value: $guess.red)
	.accentColor(.red)

$ 키워드

  • guess.red는 read-only이며 그 자체로 값이다.
  • 하지만 $guess.red는 read-write 바인딩이다.
Text(
	"R: \(Int(guess.red * 255.0))"
		+ "  G: \(Int(guess.green * 255.0))"
		+ "  B: \(Int(guess.blue * 255.0))"
)
  • 위 Text처럼 변경이 필요하지 않고, 값만 필요한 경우 $ prefix가 필요 없다.

 

@Binding

  • 부모 뷰에서 초기 값을 받아 이를 변경(mutate)한다.
struct ColorSlider: View {
	@Binding var value: Double
	var trackColor: Color

	...

	Slider(value: $value)
		.accentColor(trackColor)
}

// Before
Slider(value: $guess.red)
	.accentColor(.red)


// After
ColorSlider(value: $guess.red, trackColor: .red)

 

Presenting an alert

@State var showScore = false

Button("Hit Me!") {
	showScore = true
	...
}
.alert(isPresented: $showScore) {
	Alert(
		title: Text("Your Score"),
		message: Text(String(game.scoreRound)),
		dismissButton: .default(Text("OK")) {
			game.startNewRoung()						
		}
	)
}
  • 버튼을 클릭할 경우 showScore 값이 true로 되며, State 값 변경으로 전체 body가 다시 그려지게 되면서 alert modifer 동작
  • $showScore 바인딩을 전달하는 이유는 사용자가 Alert를 dismiss 할 경우 showScore 값을 false로 변경하기 때문이다.

 

Make Conditional

 

if !showScore {
	Text("R: ??? G: ??? B: ???")
		.padding()
} else {
	Text(game.target.intString())
		.padding()
}

 

  • View를 Command-click 하고, Make Conditional을 선택하여 if-else 구문을 추가할 수 있다.

 

 

 

반응형