suvera-dev ๐Ÿฅฆ

SwiftUI) SwiftUI Essentials ๋ณธ๋ฌธ

iOS/SwiftUI

SwiftUI) SwiftUI Essentials

suvera 2023. 3. 29. 05:31

 

์ตœ๊ทผ์— ๊ฐœ๋ฐœ ์ปจํผ๋Ÿฐ์Šค์— ๊ฐ”๋‹ค๊ฐ€ ์Šค์œ  ๋ฝ๋ฟŒ๊ฐ€ ์™€์„œ

์Šค์œ  ๊ณต๋ถ€๋ฅผ ์‹œ์ž‘ํ–ˆ์–ด์š”. ์ƒˆ๋กœ์šด ๊ฑธ ๊ณต๋ถ€ํ•˜๋Š” ๊ฑด ์—ญ์‹œ ์žฌ๋ฐŒ๋„ค์šค

 

์ž๋ฃŒ๋Š” ์• ํ”Œ ๊ณต์‹ ๋ฌธ์„œ์— ์žˆ๋Š” SwiftUI Tutorials๋กœ ํ•˜๋ ค๊ตฌ์š”.

์šฐ์„  ํ•œ๋ฒˆ ์ „์ฒด์ ์œผ๋กœ ๊ฐ€๋ณ๊ฒŒ ๋ณด๊ณ  ์ถ”ํ›„ ํ•„์š”์— ๋”ฐ๋ผ ๊นŠ๊ฒŒ ๊ณต๋ถ€ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

๊ณต์‹๋ฌธ์„œ๋ผ ๋ฏฟ์Œ์ง์Šค๋Ÿฝ๊ณ  ์˜์–ด๊ณต๋ถ€๋„ ๋˜๋Š” ๊ฒƒ ๊ฐ™๊ณ  ์ข‹๋„ค์š” ( ์•„์ง๊นŒ์ง„ ? )

๊ทธ๋ฆฌ๊ณ  ๋ญ”๊ฐ€ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด์ค˜์„œ ์žฌ๋ฐŒ๋„ค์š”. ํ‚คํ‚ค. 

 

https://developer.apple.com/tutorials/swiftui

 

Introducing SwiftUI | Apple Developer Documentation

SwiftUI is a modern way to declare user interfaces for any Apple platform. Create beautiful, dynamic apps faster than ever before.

developer.apple.com

 

์ฒซ ์ฑ•ํ„ฐ๋Š” SwiftUI Essentials ์ž…๋‹ˆ๋‹ค.

 


1. Creating and Combining Views : ๋ทฐ ๋งŒ๋“ค๊ณ  ๊ฒฐํ•ฉํ•ด๋ณด๊ธฐ ~

 

- ์ฒ˜์Œ์—๋Š” ์–ด๋–ค ์•ฑ์„ ๋งŒ๋“ค ๊ฒƒ์ธ์ง€ ์„ค๋ช…ํ•ด์ค๋‹ˆ๋‹ค. ์–ด๋–ค ์•ฑ์ด๋ƒ๋ฉด์š”.

: ์ผ๋ช… ๋žœ๋“œ๋งˆํฌ์•ฑ ! ์ข‹์•„ํ•˜๋Š” ์žฅ์†Œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ์•ฑ์ด๋ผ๊ณ  ํ•˜๋„ค์š”.

 

- Landmarks uses stacks to combine and layer the image and text view components.

: ์Šคํƒ์„ ์‚ฌ์šฉํ•ด์„œ ์ด๋ฏธ์ง€์™€ ํ…์ŠคํŠธ์™€ ๊ฐ™์€ ๋ทฐ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฒฐํ•ฉํ•˜๊ณ  ๊ณ„์ธตํ™” ํ•œ๋Œ€์š”.

 

- To add a map to the view, you’ll include a standard MapKit component. As you refine the view’s design, Xcode provides real-time feedback so you can see how those changes translate into code.

: ๋ทฐ์— ์ง€๋„๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ํ‘œ์ค€ MapKit ์ปดํฌ๋„ŒํŠธ๋ฅผ ํฌํ•จ์‹œ์ผœ์•ผ ํ•œ๋Œ€์š”.

๋ทฐ ๋””์ž์ธ์„ ์„ธ๋ถ„ํ™”ํ•  ๋•Œ Xcode๋Š” ์‹ค์‹œ๊ฐ„ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜์—ฌ ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ฝ”๋“œ๋กœ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

 


 

1) ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ๋ฐ ํŒŒ์ผ ์‚ดํŽด๋ณด๊ธฐ

- ์ด ํŠœํ† ๋ฆฌ์–ผ์ด ์ง„์งœ ์ข‹์€๊ฒŒ ์ด๋ ‡๊ฒŒ ์Šคํฌ๋กค์„ ๋‚ด๋ฆฌ๋ฉด์„œ ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•ด์ค๋‹ˆ๋‹ค.

- ์ด๋Œ€๋กœ ๋”ฐ๋ผ์„œ ํ”„๋กœ์ ํŠธ ๋งŒ๋“ค๊ณ , ์ค‘์š”ํ•œ ์„ค๋ช…๋“ค๋งŒ ์ฝ์–ด์คฌ์–ด์š”.

 

- LandmarksApp.swift ํŒŒ์ผ

@main
struct LandmarksApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

An app that uses the SwiftUI app life cycle has a structure that conforms to the App protocol.

The structure’s body property returns one or more scenes, which in turn provide content for display. The @main attribute identifies the app’s entry point.

 

: ์Šค์œ  ์•ฑ ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ์‚ฌ์šฉํ•˜๋Š” ์•ฑ์€ App์ด๋ผ๋Š” ํ”„๋กœํ† ์ฝœ์„ conform ํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„๋Œ€์š” !

์ด ๊ตฌ์กฐ์˜ ๋ฐ”๋”” ํ”„๋กœํผํ‹ฐ๋Š” ํ•˜๋‚˜์ด์ƒ์˜ scenses๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , @main ์€ ์•ฑ์˜ ์ง„์ž…์ ์„ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค  !

 

- ContentView.swift ํŒŒ์ผ

 

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

By default, SwiftUI view files declare two structures. The first structure conforms to the View protocol and describes the view’s content and layout. The second structure declares a preview for that view.

: ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šค์œ ์˜ view ํŒŒ์ผ์€ ๋‘๊ฐœ์˜ ๊ตฌ์กฐ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค

-> ์ฒซ๋ฒˆ์งธ ๊ตฌ์กฐ๋Š” View๋ผ๋Š” ํ”„๋กœํ† ์ฝœ์„ conform ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ทฐ์˜ ๋‚ด์šฉ์ด๋ž‘ ๋ ˆ์ด์•„์›ƒ์„ ๊ฐ–๊ณ ์ด์จ์š”.

-> ๋‘๋ฒˆ์งธ ๊ตฌ์กฐ๋Š” ๊ทธ ๋ทฐ์˜ preview๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ( ์š”๋ ‡๊ฒŒ ํ”„๋ฆฌ๋ทฐ๋ฅผ ๋„์šฐ๋Š” ๊ฑฐ๊ตฌ๋‚˜ ! )

 

 

- Text ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋‹ˆ๊นŒ ํ”„๋ฆฌ๋ทฐ์— ๋ฐ”๋กœ ๋ฐ˜์˜์ด ๋˜๋„ค์š”.. ์•„๋‹ˆ UIKit ๋งŒ ์“ฐ๋‹ค๊ฐ€ ์Šค์œ ๋Š” ์‹ ์„ธ๊ณ„๊ธด ํ•˜๋‹ค ํžˆํžˆ ์žฌ๋ฐŒ๋”

 


2) Text View ์ปค์Šคํ„ฐ๋งˆ์ด์ง•

- ์ฝ”๋“œ๋‚˜ ์ธ์ŠคํŽ™ํ„ฐ๋ฅผ ์‚ฌ์šฉ

 

- ์ปค๋งจ๋“œ + ํด๋ฆญํ•˜๋ฉด ์ €๋ ‡๊ฒŒ ๋œจ๋Š”๋ฐ, ์ €๊ธฐ์„œ SwiftUI Inspector๋ฅผ ์„ ํƒํ•˜์‹ญ์‡ผ. ๋ˆ„๋ฅด๋ฉด ์ธ์ŠคํŽ™ํ„ฐ๊ฐ€ ๋œจ๋Š”๋ฐ, Turtle Rock์ด๋ผ๊ณ  ๋ฐ”๊ฟ”์ฃผ๊ณ  Title๋กœ ์„ค์ • ํ•ด์ค๋‹ˆ๋‹ค. ์ง์ ‘ ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•ด๋ณด๊ธฐ : .forgroundColor(.green) 

struct ContentView: View {
    var body: some View {
        Text("Turtle Rock")
            .font(.title)
            .foregroundColor(.green)
    }
}

struct ContentView_Preview: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

- swiftUI๋ฅผ ์ปค์Šคํ…€ํ•˜๊ธฐ ์œ„ํ•ด์„œ modifiers๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. modifiers๋Š” ๋ทฐ์˜ ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ทฐ๋ฅผ ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค.

- ๊ฐ modifier๋Š” ์ƒˆ๋กœ์šด ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ์˜ modifier๊ฐ€ ์ฒด์ธ์ฒ˜๋Ÿผ ์ˆ˜์ง์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.

( ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” modifier๋Š” .font , .foregroundColor์™€ ๊ฐ™์€ ๊ฑฐ )

- ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ์—์„œ Text ๋ถ€๋ถ„์„ Command๋ฅผ ๋ˆ„๋ฅด๊ณ  ํด๋ฆญํ•ด๋„ ์ธ์ŠคํŽ™ํ„ฐ๋ฅผ ์—ด ์ˆ˜ ์žˆ์–ด์š”.

- ๋‹ค์‹œ Color๋ฅผ inherited๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด .foregroundColor ์ฝ”๋“œ ๋ผ์ธ์ด ์‚ฌ๋ผ์ง. ์™€์•™ ์‹ ๊ธฐํ•˜๋‹ค ~

 

 

 


3) Stacks์„ ์‚ฌ์šฉํ•ด์„œ ๋ทฐ๋“ค์„ ๊ฒฐํ•ฉํ•ด๋ณด๊ธฐ

 

- ํƒ€์ดํ‹€๋ทฐ ์™ธ์—๋„ ๋žœ๋“œ๋งˆํฌ์— ๊ด€ํ•œ ๊ณต์›์˜ ์ด๋ฆ„์ด๋‚˜ ์œ„์น˜๊ฐ™์€ ์„ธ๋ถ€์‚ฌํ•ญ์„ ํฌํ•จํ•˜๋Š” ํ…์ŠคํŠธ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

- SwiftUI๋กœ ๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋ ˆ์ด์•„์›ƒ์ด๋‚˜ ๋™์ž‘์„ ๋ฐ”๋”” ํ”„๋กœํผํ‹ฐ์— ๊ตฌํ˜„ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค์š”.

 

But, ๋ฐ”๋”” ํ”„๋กœํผํ‹ฐ๋Š” ๋‹จ์ผ ๋ทฐ๋งŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค !!

๊ทธ๋ž˜์„œ ์Šคํƒ์„ ์“ฐ๋Š”๊ฑฐ์—์š” ! ์Šคํƒ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๋ทฐ๋ฅผ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ฑ์š”.

 

- ์Šคํƒ์€ ๋ทฐ๋“ค์„ ์ˆ˜ํ‰์ ์œผ๋กœ, ์ˆ˜์ง์ ์œผ๋กœ ํ˜น์€ ์•ž๋’ค๋กœ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- ์ด๋ฒˆ ๋‚ด์šฉ์—์„œ๋Š” ๊ฐ€๋กœ ์Šคํƒ์•ˆ์— ๊ณต์›์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ผ๊ฑฐ์—์š”

- ๊ทธ๋ฆฌ๊ณ  ์ œ๋ชฉ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ์„ธ๋กœ ์Šคํƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€๋กœ ์Šคํƒ ์œ„์— ์„ธ๋กœ ์Šคํƒ์„ ๋ฐฐ์น˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

- ์š”๋ ‡๊ฒŒ ๊ฐ€๋กœ ์Šคํƒ ์•ˆ์— ๊ณต์› ์„ธ๋ถ€์ •๋ณด๋ฅผ ๋‹ด๊ณ , ์„ธ๋กœ ์Šคํƒ์•ˆ์— ์ œ๋ชฉ๊ณผ ๊ณต์›์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ€๋กœ์Šคํƒ์„ ๋„ฃ์„ ๊ฑฐ๋ž๋‹ˆ๋‹น.

 

์ž, 1๋ฒˆ. ์ปค๋งจ๋“œ + ํด๋ฆญ์œผ๋กœ ํŒ์˜ค๋ฒ„ ๋„์šฐ๊ณ , Embed in VStack์„ ์„ ํƒํ•œ๋‹ค. 

- ๊ทธ๋Ÿฌ๋ฉด VStack์œผ๋กœ ๊ฐ์‹ธ์ ธ์š”.

- ๊ทธ๋‹ค์Œ์—” + ๋ฒ„ํŠผ์œผ๋กœ Text ๋“œ๋ž˜๊ทธํ•ด์„œ ์ถ”๊ฐ€ํ•œ๋‹ค์Œ์— Joshua Tree National Park๋ผ๋Š” ๋žœ๋“œ๋งˆํฌ๋ฅผ ์ถ”๊ฐ€.

- ํฐํŠธ์˜ ์œ„์น˜๋ฅผ subheadline์œผ๋กœ ์…‹ ํ•ฉ๋‹ˆ๋‹ค.

- VStack ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ํŽธ์ง‘ํ•˜์—ฌ ์•ž ๊ฐ€์žฅ์ž๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ทฐ๋ฅผ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. 

- ์š”๋ ‡๊ฒŒ VStack์˜ ์ด๋‹ˆ์…œ๋ผ์ด์ €์—๋Š” ์ •๋ ฌ ๊ธฐ์ค€์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹น

- ๊ทธ ๋‹ค์Œ์— ์ € ์กฐ์Šˆ์•„ ์–ด์ฉŒ๊ตฌ ๊ณต์›์„ ์œ„์— ํ–ˆ๋˜ ๋ฐฉ๋ฒ•๋Œ€๋กœ Embed HStack์„ ํ•ด์ฃผ์„ธ์š”. 

- ๊ทธ๋Ÿฐ๋‹ค์Œ์— Text๋กœ ์บ˜๋ฆฌํฌ๋‹ˆ์•„๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š”๊ฑฐ์—์—ฌ. ๊ทธ๋Ÿฌ๋ฉด ๋‚˜๋ž€ํžˆ HStack์— ๋“ค์–ด๊ฐ€๊ณ , ๊ฐ€์šด๋ฐ์— Spacer๋ฅผ ์ถ”๊ฐ€ํ•ด์ค„๊ฑฐ์—์š”.

 

- ๋””๋ฐ”์ด์Šค์˜ ์ „์ฒด ๊ฐ€๋กœ ๋„ˆ๋น„๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‘ ๊ฐœ์˜ ํ…์ŠคํŠธ๋ทฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์ˆ˜ํ‰ ์Šคํƒ์— Spacer๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ณต์›๊ณผ ์ฃผ์†Œ๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Spacer๋Š” ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํฌํ•จ๋œ ๋ทฐ๊ฐ€ ์ฝ˜ํ…์ธ ์— ์˜ํ•ด ์ •์˜๋œ ์‚ฌ์ด์ฆˆ๋งŒ ๊ฐ–๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋ถ€๋ชจ ๋ทฐ์˜ ๋ชจ๋“  ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค ! ์•„๋ž˜์ฒ˜๋Ÿผ์š” ! 

- ๋งˆ์ง€๋ง‰์œผ๋กœ ๋žœ๋“œ๋งˆํฌ์™€ ์„ธ๋ถ€ ๋‚ด์šฉ ์‚ฌ์ด์— ์•ฝ๊ฐ„์˜ ๊ฑฐ๋ฆฌ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ padding() ์ˆ˜์ •์ž(modifier)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 


4) ์ปค์Šคํ…€ ์ด๋ฏธ์ง€๋ทฐ ๋งŒ๋“ค์–ด๋ณด๊ธฐ

- ํŒŒ์ผ์— ๋” ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋Œ€์‹ ์— ์ด๋ฏธ์ง€์— ๋งˆ์Šคํฌ, ํ…Œ๋‘๋ฆฌ, ๊ทธ๋ฆผ์ž ํšจ๊ณผ ๋“ฑ์„ ์ ์šฉํ•˜๋Š” ์ปค์Šคํ…€ ๋ทฐ๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹น.

- ์ด๋ฏธ์ง€ ์—์…‹ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์Šค๋ฃจํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค ! ์•„๋ž˜ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ํ•˜์‹ฌ ๋ฉ๋‹ˆ๋‹น.

 

turtlerock.jpg
0.08MB

- ์ƒˆ๋กœ์šด ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•ด์ค„๊ฒ๋‹ˆ๋‹ค SwiftUI View๋ผ๋Š” ์นœ๊ตฌ์—์š”. UIKit ์˜ UIView๋ž‘ ๊ฐ™์€ ์• ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜๊ฒ ์ฃ ?

- ๊ทธ๋ฆฌ๊ณ  Image(_:) ์ด๋‹ˆ์…œ๋ผ์ด์ ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Turtle Rock ์ด๋ฏธ์ง€๋กœ ๋ฐ”๊พธ์„ธ์š”. ์ง„์งœ.. ๊ฐ„๋‹จํ•˜๋„ค ์Šค์œ .. ํผ ๋ฏธ์ณค๋‹ค.

- ์ด๋ฏธ์ง€ ๋ชจ์–‘์„ ์›ํ˜• ํด๋ฆฌํ•‘ ๋ชจ์–‘์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด clipShape(Circle())๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š” !
: ์›ํ˜• ํƒ€์ž…์€ ๋งˆ์Šคํฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ณ  ์ฑ„์šฐ๊ฑฐ๋‚˜ ์ŠคํŠธ๋กœํฌ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ๋ทฐ๋กœ์จ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- ํšŒ์ƒ‰ ์„ ์ด ์žˆ๋Š” ๋‹ค๋ฅธ ์›์„ ๋งŒ๋“  ๋‹ค์Œ ์˜ค๋ฒ„๋ ˆ์ด๋กœ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฏธ์ง€์— ํ…Œ๋‘๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , 7ํฌ์ธํŠธ ๋ฐ˜๊ฒฝ์˜ shadow๋ฅผ ๋งŒ๋“ ๋‹ค์Œ ๋‹ค์‹œ stroke๋ฅผ white๋กœ ๋ฐ”๊ฟ”์ฃผ์„ธ์šฉ.

import SwiftUI

struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
            .clipShape(Circle())
            .overlay {
                Circle().stroke(.white, lineWidth: 4)
            }
            .shadow(radius: 7)
    }
}

struct CircleImage_Previews: PreviewProvider {
    static var previews: some View {
        CircleImage()
    }
}

5) ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ SwiftUI ๋ทฐ๋“ค์„ ์‚ฌ์šฉํ•ด๋ณด์ž. 

 

- ๋‹ค์Œ์œผ๋กœ ์ง€์ •๋œ ์ขŒํ‘œ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ํ•˜๋Š” ์ง€๋„๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. 

- Mapkit์„ ์‚ฌ์šฉํ•ด์„œ ์ง€๋„๋ฅผ ๋ Œ๋”๋ง ํ• ๊ฑฐ์—์š” !

- MapView๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค. 

- ๊ทธ๋ฆฌ๊ณ  Step3์„ ์ฝ์–ด๋ณด๋ฉด, ์ง€๋„์— ๋Œ€ํ•œ ์ง€์—ญ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” privateํ•œ state๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ค˜์š”.

- You use the @State attribute to establish a source of truth for data in your app that you can modify from more than one view. SwiftUI manages the underlying storage and automatically updates views that depend on the value.

: ์—ฌ๊ธฐ์„œ @State ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ•˜๋‚˜ ์ด์ƒ์˜ ๋ทฐ๋กœ๋ถ€ํ„ฐ ์ˆ˜์ •ํ• ์ˆ˜ ์žˆ๋Š” ์•ฑ์˜ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด์„œ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” source๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

- SwiftUI manages the underlying storage and automatically updates views that depend on the value.

: SwiftUI๋Š” ๊ธฐ๋ณธ storage๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ๊ฐ’์— ๋”ฐ๋ผ ์ž๋™์ ์œผ๋กœ ๋ทฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ค€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 


@State์— ๋Œ€ํ•ด์„œ๋Š” ๋” ์ž์„ธํžˆ ๊ณต๋ถ€๋ฅผ ํ•ด์ค˜์•ผํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ๋งŒ ์ •๋ฆฌํ•˜์ž๋ฉด,

 

- State๋Š” ๋ทฐ๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ(Property Wrapper)์ž…๋‹ˆ๋‹ค.

- ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ๋Š” Swift 5.1๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.

- ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ๋Š” ์‰ฝ๊ฒŒ ๋งํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ๋ณ„๋„์˜ ์ฝ”๋”ฉ ์—†์ด ์–ด๋…ธํ…Œ์ด์…˜๋งŒ ์„ ์–ธํ•ด๋„ ๋ทฐ์—์„œ ์ˆ˜์ •์ด๋‚˜ ์ฝ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ์บก์Šํ™”๋ฅผ ๋Œ€์‹ ํ•ด์ค๋‹ˆ๋‹ค. 

- UIKit ์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ๋Š” ์–ด๋– ํ•œ ๋ณ€์ˆ˜์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ๋ฉด ํ•ด๋‹น ๋ณ€ํ™”๋ฅผ ์ง์ ‘ ๊ด€์ฐฐํ•˜๊ณ  ๋ฐ˜์˜ํ•ด ์ฃผ์–ด์•ผ ํ–ˆ๋Š”๋ฐ SwiftUI ์—์„œ๋Š” property wrapper๋ฅผ ํ™œ์šฉํ•ด ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ์ž๋™ํ™” ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 

์ €๋„ ์ฒ˜์Œ ๊ณต๋ถ€ํ•œ ๊ฐœ๋…์ด๋ผ ๊ณต์‹๋ฌธ์„œ์™€ ๋ธ”๋กœ๊ทธ๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ด์•ผ๊ฒ ๋„ค์š” !


 

- ๋‹ค์Œ์€ ๊ธฐ๋ณธ Text๋ฅผ ์ง€์—ญ์„ ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋Š” Map view๋กœ ๋ฐ”๊ฟ”์ค๋‹ˆ๋‹ค.

- By prefixing a state variable with $, you pass a binding, which is like a reference to the underlying value. When the user interacts with the map, the map updates the region value to match the part of the map that’s currently visible in the user interface.

: state ๋ณ€์ˆ˜์— ์ ‘๋‘์‚ฌ $๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๊ธฐ๋ณธ ๊ฐ’์— ๋Œ€ํ•œ ์ฐธ์กฐ์™€ ๊ฐ™์€ ๋ฐ”์ธ๋”ฉ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ map์ด๋ž‘ ์ƒํ˜ธ์ž‘์šฉํ•  ๋•Œ, ํ˜„์žฌ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ๋ณด์—ฌ์ง€๋Š” ์ง€๋„ ๋ถ€๋ถ„๊ณผ ์ผ์น˜ํ•˜๋„๋ก ์ง€์—ญ ๊ฐ’์„ ์—…๋ฐ์ดํ•ฉ๋‹ˆ๋‹ค.

 

When previews are in static mode, they only fully render native SwiftUI views. For the Map view, you’ll need to switch to a live preview to see it render.

: ํ”„๋ฆฌ๋ทฐ๊ฐ€ ์ •์  ๋ชจ๋“œ์ผ๋•Œ๋Š” ๋„ค์ดํ‹ฐ๋ธŒ SwiftUI ๋ทฐ๋งŒ ๋ Œ๋”๋ง ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋งต๋ทฐ์˜ ๊ฒฝ์šฐ ์‹ค์‹œ๊ฐ„ ํ”„๋ฆฌ๋ทฐ๋กœ ๋ฐ”๊ฟ”์ค˜์•ผํ•ฉ๋‹ˆ๋‹ค.

struct MapView: View {
    // ์ง€๋„์— ๋Œ€ํ•œ ์ง€์—ญ ์ •๋ณด๋ฅผ ๋ณด์œ ํ•˜๋Š” state ๋ณ€์ˆ˜
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),
        span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
    )
    
    var body: some View {
        Map(coordinateRegion: $region)
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}

 


6) ์ƒ์„ธ๋ณด๊ธฐ ๊ตฌ์„ฑํ•˜๊ธฐ

๋žœ๋“œ๋งˆํฌ ์ƒ์„ธ๋ณด๊ธฐ ์•ฑ์˜ ์ตœ์ข… ๋””์ž์ธ ์™„์„ฑํ•˜๊ธฐ

 

1. ์ƒˆ  VStack์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ƒ์œ„์— ์œ„์น˜ํ•œ VStack ์€ ๋‘์‹œ๊ณ  ๊ทธ ์•ˆ์— ์žˆ๋˜ 3๊ฐœ์˜ ํ…์ŠคํŠธ๋ทฐ๋ฅผ ํฌํ•จ์‹œํ‚ค์„ธ์š”.

 

2. ์ปค์Šคํ…€ ๋งต๋ทฐ๋ฅผ ์Šคํƒ ์ƒ๋‹จ์— ์ถ”๊ฐ€ํ•˜์‹œ๊ณ  frame(width:height:)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งต๋ทฐ์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์„ค์ •ํ•˜์„ธ์š”.
- height ๋ฏธํ„ฐ๋งŒ ์ •์˜๋ฅผ ํ•˜๋ฉด ์ž๋™์ ์œผ๋กœ ์ฝ˜ํ…์ธ ์˜ width๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ์—๋Š” ๋งต๋ทฐ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ณต๊ฐ„์— ๊ฝ‰ ์ฐจ๊ฒŒ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

 

3. ์Šคํƒ์— CircleImage๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

 

4. ๋งต๋ทฐ ์œ„์— ์ด๋ฏธ์ง€๋ทฐ๋ฅผ ์ž๋ฆฌํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์ด๋ฏธ์ง€์— ์˜คํ”„์…‹์„ ์ˆ˜์ง์ ์œผ๋กœ -130, ๋ทฐ๋กœ๋ถ€ํ„ฐ ํ•˜๋‹จ ํŒจ๋”ฉ(bottom padding) -130์„ ์ฃผ์„ธ์š”
์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด๋ฏธ์ง€๋ฅผ ์œ„๋กœ ์ด๋™์‹œ์ผœ์„œ ํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ๊ณต๊ฐ„์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

struct ContentView: View {
    var body: some View {
        VStack {
            MapView()
                .frame(height: 300)

            CircleImage()
                .offset(y: -130)
                .padding(.bottom, -130)

            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)

                HStack {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
            }
            .padding()
        }
    }
}

 

- ์ตœ์ƒ๋‹จ์— ์žˆ๋Š” VStack์— spacer๋ฅผ ๋„ฃ์–ด์„œ ์ฝ˜ํ…์ธ ๋ฅผ ํ™”๋ฉด ์ƒ๋‹จ์œผ๋กœ ๋ฐ‰๋‹ˆ๋‹ค.

- ์ง€๋„ ๋‚ด์šฉ์„ ํ™”๋ฉด์˜ ์ƒ๋‹จ ๊ฐ€์žฅ์ž๋ฆฌ๋กœ ํ™•์žฅํ•˜๋ ค๋ฉด edgeIgnoringSafeArea (.top) ์ˆ˜์ •์ž(modifier)๋ฅผ ๋งต๋ทฐ์— ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

- ๋žœ๋“œ๋งˆํฌ ์„ธ๋ถ€์ •๋ณด๋ฅผ ์ถ”๊ฐ€ : Divider ์ถ”๊ฐ€ !

- ๋งˆ์ง€๋ง‰์œผ๋กœ, HStack์— ํฌํ•จ๋œ ์• ๋“ค์„ subheadline์œผ๋กœ ์„ค์ •ํ•˜๊ณ  secondary color๋ฅผ ์ ์šฉ์‹œ์ผœ์ค๋‹ˆ๋‹น.

struct ContentView: View {
    var body: some View {
        VStack {
            MapView()
                .ignoresSafeArea(edges: .top)
                .frame(height: 300)

            CircleImage()
                .offset(y: -130)
                .padding(.bottom, -130)

            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)
                HStack {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
                .font(.subheadline)
                .foregroundColor(.secondary)

                Divider()

                Text("About Turtle Rock")
                    .font(.title2)
                Text("Descriptive text goes here.")
            }
            .padding()

            Spacer()
        }
    }
}

์ตœ์ข… ์ฝ”๋“œ๋Š” ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค์š” !

๊ทธ๋ฆฌ๊ณ  ๋งจ ๋งˆ์ง€๋ง‰์—” ์ด๋ ‡๊ฒŒ ๊ฐœ๋…์„ ์ž˜ ์ดํ•ดํ–ˆ๋Š”์ง€ ํ€ด์ฆˆ๋„ ๋‚˜์˜จ๋‹ต๋‹ˆ๋‹ค ใ…‹ใ…‹ใ…‹ ์นœ์ ˆํ•œ ์• ํ”Œ ํŠœ ํ†  ๋ฆฌ ์–ผ

 

 

ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ž„์˜์ ์œผ๋กœ ๋ฒˆ์—ญํ•ด์„œ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค ! 

์›๋ณธ ์„ค๋ช…์€ ๊ณต์‹ ํŠœํ† ๋ฆฌ์–ผ์„ ๋ด์ฃผ์„ธ์—ฌ ~

 

 

์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌ๋ ์ค„ ์•Œ์•˜๋Š”๋ฐ ํ•˜๋‚˜์”ฉ ํ•˜๋‹ˆ๊นŒ ๋‚ด์šฉ์ด ๋งŽ๋„ค์š”. 

๋‹ค์Œ๋ถ€ํ„ฐ๋Š” ๊ตณ์ด ๋‹ค ์ •๋ฆฌํ•˜์ง€๋Š” ์•Š๊ณ , ์ „์ฒด ์ฝ”๋“œ ๋ฐ ์ค‘์š”ํ•œ ๋‚ด์šฉ๋“ค๋งŒ ์ •๋ฆฌํ•ด์•ผ๊ฒ ์–ด์š” ! ใ…Žใ…Ž

์–ด์ฐจํ”ผ ํŠœํ† ๋ฆฌ์–ผ์— ๋“ค์–ด๊ฐ€๋ฉด ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•ด์ฃผ๋‹ˆ๊นŒ ๊ทธ๊ฑฐ ๋ณด๋ฉด์„œ ์ฐจ๊ทผ์ฐจ๊ทผ ๋”ฐ๋ผํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋„ค์šค.

 

 

'iOS > SwiftUI' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

SwiftUI) Drawing and Animation 1 - Drawing Paths and Shapes  (0) 2023.04.02
SwiftUI) SwiftUI Essentials 3 - Handling User Input  (4) 2023.03.31
SwiftUI) SwiftUI Essentials - 2 Building Lists and Navigation  (0) 2023.03.29
Comments