Closed
28

学習メモ:Introduction to SwiftUI - WWDC 2020 - Videos - Apple Developer

Viewをcommand + クリックするとメニューが表示される

Show UI Inspector
プレビューを見ながら調整できる

プレビュー画面でcommand+optionでクリックすると同じメニューが開く

fontなどの属性を"modifier"と呼ぶ

Viewを選択、"Embed in List"を選ぶとListで展開

modiferを検索して、ドラッグ&ドロップで適用

Viewを command + クリック で Extract Subview を選択するとViewを切り出せる

            List(sandwiches) { sandwich in
                SandwichCell(sandwich: sandwich)
            }

            List {
                ForEach(sandwiches) { sandwich in
                    SandwichCell(sandwich: sandwich)
                }
                HStack {
                    Spacer()
                    Text("\(sandwiches.count) sandwitches")
                        .foregroundColor(.secondary)
                    Spacer()
                }
            }

に変える

PreviewProviderにNavigationViewを追加するとプレビューでNavigationViewの動作が確認できる

struct SandwichDetail: View {
    var sandwich: Sandwich
    var body: some View {
        Image(systemName: "camera")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .navigationTitle(sandwich.name)
    }
}

struct SandwichDetail_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            SandwichDetail(sandwich: testData[0])
        }
    }
}

tapで画像のzoomを切り替え

struct SandwichDetail: View {
    var sandwich: Sandwich
    @State private var zoomed = false
    var body: some View {
        Image(systemName: "camera")
            .resizable()
            .aspectRatio(contentMode: zoomed ? .fill : .fit)
            .onTapGesture {
                zoomed.toggle()
            }
            .navigationTitle(sandwich.name)
    }
}

画像をセーフエリアも含めて画面全体に拡大したいときはモディフィアを追加する

       .edgesIgnoringSafeArea(.bottom)

タップした時の動作にアニメーションを加える

            .onTapGesture {
                withAnimation {
                    zoomed.toggle()
                }
            }
    var body: some View {
        VStack {
            Spacer(minLength: 0)
            Image(systemName: "camera")
                .resizable()
                .aspectRatio(contentMode: zoomed ? .fill : .fit)
                .onTapGesture {
                    withAnimation {
                        zoomed.toggle()
                    }
                }
            Spacer(minLength: 0)
            HStack {
                Spacer()
                Label("Spicy", systemImage: "flame.fill")
                Spacer()
            }
            .padding(.all)
            .font(Font.headline.smallCaps())
            .background(Color.red)
            .foregroundColor(.white)
        }
        .edgesIgnoringSafeArea(.bottom)
        .navigationTitle(sandwich.name)
    }

プレビューを複数表示して違いを確認する


struct SandwichDetail_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            NavigationView {
                SandwichDetail(sandwich: testData[0])
            }
            NavigationView {
                SandwichDetail(sandwich: testData[1])
            }
        }
    }
}

トランジションを追加

            if sandwich.isSpicy && !zoomed {
                HStack {
                    Spacer()
                    Label("Spicy", systemImage: "flame.fill")
                    Spacer()
                }
                .padding(.all)
                .font(Font.headline.smallCaps())
                .background(Color.red)
                .foregroundColor(.white)
                .transition(.move(edge: .bottom))
            }

ターゲットを(シミュレータの)iPadに切り替えるとプレビューがiPadに切り替わる

ターゲットをmacに変更するとmacアプリとして表示

新しいモデルを用意

class SandwichStore: ObservableObject {
    @Published var sandwiches: [Sandwich]
    init(sandwiches: [Sandwich] = []) {
        self.sandwiches = sandwiches
    }
}

let testStore = SandwichStore(sandwiches: testData)

  • ObservableObject
  • @Published

App本体にStoreを追加

@main
struct wwdc20_swiftui_introductionApp: App {
    @StateObject private var store = SandwichStore()
    var body: some Scene {
        WindowGroup {
            ContentView(store: store)
        }
    }
}

ContentViewを変更

struct ContentView: View {
    @ObservedObject var store: SandwichStore

    var body: some View {
        NavigationView {
            List {
                ForEach(store.sandwiches) { sandwich in
                    SandwichCell(sandwich: sandwich)
                }
                HStack {
                    Spacer()
                    Text("\(store.sandwiches.count) sandwitches")
                        .foregroundColor(.secondary)
                    Spacer()
                }
            }
            .navigationTitle("Sandwiches")

            Text("Select a sandwich")
                .font(.title)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(store: testStore)
    }
}
  • @ObservedObject var store: SandwichStore

リストの編集に対応したコードスニペット

    func makeSandwich() {
        withAnimation {
            store.sandwiches.append(Sandwich(name: "new sandwich", isSpicy: true))
        }
    }

    func moveSandwiches(from: IndexSet, to: Int) {
        withAnimation {
            store.sandwiches.move(fromOffsets: from, toOffset: to)
        }
    }

    func deleteSandwiches(offsets: IndexSet) {
        withAnimation {
            store.sandwiches.remove(atOffsets: offsets)
        }
    }

iOSだけToolBarにボタンを表示する

            .toolbar {
                #if os(iOS)
                    EditButton()
                #endif
            }

Addボタンを追加したけど表示されない

            .toolbar {
                #if os(iOS)
                EditButton()
                #endif
                Button("Add", action: makeSandwich)
            }

プレビューでダークモードのテストができる

wwdcのビデオとzennをサイドバイサイドに並べて作業しました。

感想

  • 実機を使用しないでプレビューだけでアプリを組み立てられるので便利
  • XcodeのGUIでリファクタリングやコンポーネントの変更ができる
このスクラップは5ヶ月前にクローズされました
ログインするとコメントできます