SwiftUI チュートリアルをやってみる - Creating and Combining Views
SwiftUI チュートリアル
SwiftUIの学習の為、チュートリアルを丁寧にやってみようと思います。
今回は Chapter 1 - SwiftUI Essentials
の Creating and Combining Views
をやってみます。
試した環境
- Xcode: 14.0.1
- MacBook Pro (13-inch, M1, 2020)
- macOS Monterey 12.6
- メモリ 16 GB
Creating and Combining Views
Viewをどの様に構築していくかを Landmark
アプリのランドマーク詳細画面を作成しながら進めていきます。
Section1 - Create a New Project and Explore the Canvas
XcodeでSwiftUIを使用するプロジェクトを作成します。
-
Step1
- Xcodeを開き
Create a new Xcode project
を選択します
- Xcodeを開き
-
Step2
- テンプレートから iOS App を選択します
- テンプレートから iOS App を選択します
-
Step3
- ※ チュートリアルでは
Interface
とLanguage
を選択できるようなUIを説明していたが、最新のXcodeだとデフォルトでSwiftUI+Swiftが選択されておりました
- ※ チュートリアルでは
-
Step4
-
SwiftUIのアプリではAppプロトコルに準拠した構造体を実装します
- bodyプロパティでは1つ以上のSceneを返します
-
@main
はエントリポイントを示します
import SwiftUI @main struct LandmarksApp: App { var body: some Scene { WindowGroup { ContentView() } } }
-
-
Step5
- SwiftUIのViewファイルではデフォルト2つの構造体が定義されています
- 1つ目は
View
プロトコルに準拠した構造体 - 2つ目は Preview用の構造体
- 1つ目は
import SwiftUI 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() } }
- SwiftUIのViewファイルではデフォルト2つの構造体が定義されています
-
Step6
- 選択しているデバイスでPreviewが変わります :sparkles:
-
DeviceがMacの場合
-
DeviceがiPhoneの場合
-
- 選択しているデバイスでPreviewが変わります :sparkles:
-
Step7
- Textの文字列を修正するとPreviewも変わります
- Textの文字列を修正するとPreviewも変わります
Section2 - Customize the Text View
コードやインスペクタを使用して Text View
をカスタムします。
-
Step1 - 3
-
inspectorを使って文字列やfontを変更します (その他色々機能があります)
-
ソースコードは以下に修正されていました
Text("Hello") .font(.title)
-
-
Step4
- テキストのカラーを
green
に変更しますText("Hello") .font(.title) .foregroundColor(.green)
- テキストのカラーを
-
Step5
- 先ほどのinspectorがコード上からでも表示できます
- 先ほどのinspectorがコード上からでも表示できます
Section3 - Combine Views Using Stacks
Viewをグループ化するスタックを使用してレイアウトを調整します。
-
Step1-2
-
Embed in VStack
で VStackの中にTextを格納し、新たなTextを追加します
-
-
Step4-5
-
VStack(alignment: .leading)
とすることで左寄せにできます
-
-
Step6 - 7
- HStack追加し、新たなTextを追加します
- HStack追加し、新たなTextを追加します
-
Step8
-
Spacer
を追加して横方向の間にスペースを置来ますHStack { Text("Joshua Tree National Park") .font(.subheadline) Spacer() Text("California") .font(.subheadline) }
-
- Step9
- 最後に
padding
をVStack
に追加しますVStack(alignment: .leading) { Text("Turtle Rock") .font(.title) HStack { Text("Joshua Tree National Park") .font(.subheadline) Spacer() Text("California") .font(.subheadline) } }.padding()
- 最後に
Section 4 - Create a Custom Image View
Image Viewをカスタムします。
-
Step1
- 新規画像リソースを作成、リソース名を
turtlerock
に変更します
- 新規画像リソースを作成、リソース名を
-
Step2
- 新しいSwiftUI Viewファイルを作成します
- 新しいSwiftUI Viewファイルを作成します
-
Step3
-
Text("Hello, World!")
をImage
に変更しますstruct CircleImage: View { var body: some View { Image("turtlerock") } }
-
-
Step4
-
clipShape(Circle())
を追加して円形にしますstruct CircleImage: View { var body: some View { Image("turtlerock").clipShape(Circle()) } }
-
- Step5 - 7
-
overlay modifier を利用して円に枠をつけます
- 色を白色に変更
- shadowをつける (
radius: 7
)struct CircleImage: View { var body: some View { Image("turtlerock") .clipShape(Circle()) .overlay { Circle().stroke(.white, lineWidth: 4) }.shadow(radius: 7) } }
-
overlay modifier を利用して円に枠をつけます
Section 5 - Use SwiftUI Views From Other Frameworks
MapKit
の MapView
を使用し地図を表示します。
-
Step1
- 新規
SwiftUI View
をMapView.swift
というファイル名で作成します
- 新規
-
Step2
-
import MapKit
を追加します
-
-
Step3
-
@State
アトリビュートを使用し、マップのRegionを保持するプライベートステート変数を作成しますimport SwiftUI import MapKit struct MapView: View { @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 { Text("Hello, World!") } } struct MapView_Previews: PreviewProvider { static var previews: some View { MapView() } }
-
-
Step4
-
Text("Hello, World!")
の部分をMap(coordinateRegion: $region)
に置き換える - プライベートステート変数に
$
を指定して設定すると binding され状態に応じて更新される様になります
-
-
Step5
-
Live Preview
モードを選択するとプレビューで実際にMapを触ることができます。
-
Section 6 - Compose the Detail View
これまでのViewを組み合わせLandmark詳細ビューの最終デザインを作成します
-
Step1
- Project navigatorから
ContentView.swift
を開きます
- Project navigatorから
-
Step2
- 一番外側に
VStack
を追加します
- 一番外側に
-
Step3
-
以前作成した
MapView
を先ほど追加したVStack
の先頭に追加します-
frame(width:height:).
を用いてMapView
のサイズを固定します - ※ heightのみを指定した場合、Viewはそのコンテンツの幅に合わせて自動的にサイズ調整されます。
- この場合、MapViewは利用可能なスペースを埋めるように拡張されます。
struct ContentView: View { var body: some View { VStack { MapView().frame(height: 300) // 追加 VStack(alignment: .leading) { Text("Turtle Rock") .font(.title) HStack { Text("Joshua Tree National Park") .font(.subheadline) Spacer() Text("California") .font(.subheadline) } }.padding() } } }
-
-
-
Step4
- ここでも
Live Preview
モードで確認できます
- ここでも
-
Step5
-
以前作成した
CircleImage
をMapView
の下に追加しますstruct ContentView: View { var body: some View { VStack { MapView().frame(height: 300) CircleImage() // 追加 VStack(alignment: .leading) { Text("Turtle Rock") .font(.title) HStack { Text("Joshua Tree National Park") .font(.subheadline) Spacer() Text("California") .font(.subheadline) } }.padding() } } }
-
- Step6
-
offset
とpadding
を使用して画像の位置を調整しますCircleImage() .offset(y: -130) .padding(.bottom, -130)
-
- Step7
-
外側の
VStack
の一番下にSpacer
を追加し、コンテンツを上部に押し上げます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() Spacer() // 追加 } } }
-
- Step8
-
MapView
を画面の上端まで広げる為ignoresSafeArea(edges: .top)
を追加しますMapView() .ignoresSafeArea(edges: .top) // 追加 .frame(height: 300)
-
- Step9
-
Divider
を設置し詳細を追加します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) } Divider() // 追加 Text("About Turtle Rock") .font(.title2) // 追加 Text("Descriptive text goes here.") // 追加 }.padding() Spacer() } } }
-
- Step10
-
グループに対して指定する
HStack { Text("Joshua Tree National Park") .font(.subheadline) Spacer() Text("California") .font(.subheadline) }
-
上記部分を以下に変更する
HStack { Text("Joshua Tree National Park") Spacer() Text("California") } .font(.subheadline) // 共通する部分を外だし .foregroundColor(.secondary) // カラーの設定
-
Discussion