ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
SwiftUIの基本
Appleの宣言型ユーザーインターフェイスフレームワークである、SwiftUIのツアーにご参加ください。ビュー、状態変数、レイアウトなど、SwiftUIでアプリを構築するうえで基本となる概念について解説します。豊富な機能により充実した体験を提供するアプリを実現し、独自性のあるカスタムコンポーネントを作成するうえで役立つ、多彩なAPIもご紹介します。SwiftUI初心者の方も、経験豊富なデベロッパの方も、SwiftUIのメリットを活用して優れたアプリを構築する方法を習得できます。
関連する章
- 0:00 - Introduction
- 1:34 - Fundamentals of views
- 13:06 - Bulit-in capability
- 17:36 - Across all platforms
- 20:30 - SDK interoperability
リソース
関連ビデオ
WWDC24
WWDC20
-
ダウンロードArray
-
-
2:30 - Declarative views
Text("Whiskers") Image(systemName: "cat.fill") Button("Give Treat") { // Give Whiskers a treat }
-
2:43 - Declarative views: layout
HStack { Label("Whiskers", systemImage: "cat.fill") Spacer() Text("Tightrope walking") }
-
2:56 - Declarative views: list
struct ContentView: View { @State private var pets = Pet.samplePets var body: some View { List(pets) { pet in HStack { Label("Whiskers", systemImage: "cat.fill") Spacer() Text("Tightrope walking") } } } } struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String init(_ name: String, kind: Kind, trick: String) { self.name = name self.kind = kind self.trick = trick } static let samplePets = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking"), Pet("Roofus", kind: .dog, trick: "Home runs"), Pet("Bubbles", kind: .fish, trick: "100m freestyle"), Pet("Mango", kind: .bird, trick: "Basketball dunk"), Pet("Ziggy", kind: .lizard, trick: "Parkour"), Pet("Sheldon", kind: .turtle, trick: "Kickflip"), Pet("Chirpy", kind: .bug, trick: "Canon in D") ] }
-
3:07 - Declarative views: list
struct ContentView: View { @State private var pets = Pet.samplePets var body: some View { List(pets) { pet in HStack { Label(pet.name, systemImage: pet.kind.systemImage) Spacer() Text(pet.trick) } } } } struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String init(_ name: String, kind: Kind, trick: String) { self.name = name self.kind = kind self.trick = trick } static let samplePets = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking"), Pet("Roofus", kind: .dog, trick: "Home runs"), Pet("Bubbles", kind: .fish, trick: "100m freestyle"), Pet("Mango", kind: .bird, trick: "Basketball dunk"), Pet("Ziggy", kind: .lizard, trick: "Parkour"), Pet("Sheldon", kind: .turtle, trick: "Kickflip"), Pet("Chirpy", kind: .bug, trick: "Canon in D") ] }
-
4:24 - Declarative and imperative programming
struct ContentView: View { @State private var pets = Pet.samplePets var body: some View { Button("Add Pet") { pets.append(Pet("Toby", kind: .dog, trick: "WWDC Presenter")) } List(pets) { pet in HStack { Label(pet.name, systemImage: pet.kind.systemImage) Spacer() Text(pet.trick) } } } } struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String init(_ name: String, kind: Kind, trick: String) { self.name = name self.kind = kind self.trick = trick } static let samplePets = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking"), Pet("Roofus", kind: .dog, trick: "Home runs"), Pet("Bubbles", kind: .fish, trick: "100m freestyle"), Pet("Mango", kind: .bird, trick: "Basketball dunk"), Pet("Ziggy", kind: .lizard, trick: "Parkour"), Pet("Sheldon", kind: .turtle, trick: "Kickflip"), Pet("Chirpy", kind: .bug, trick: "Canon in D") ] }
-
5:33 - Layout container
HStack { Label("Whiskers", systemImage: "cat.fill") Spacer() Text("Tightrope walking") }
-
5:41 - Container views
struct ContentView: View { var body: some View { HStack { Image(whiskers.profileImage) VStack(alignment: .leading) { Label("Whiskers", systemImage: "cat.fill") Text("Tightrope walking") } Spacer() } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
6:23 - View modifiers
struct ContentView: View { var body: some View { Image(whiskers.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(.green, lineWidth: 2) } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
7:05 - Custom views: Intro
struct PetRowView: View { var body: some View { // ... } }
-
7:14 - Custom views
struct PetRowView: View { var body: some View { Image(whiskers.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(.green, lineWidth: 2) } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
7:20 - Custom views: iteration
struct PetRowView: View { var body: some View { HStack { Image(whiskers.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle() .stroke(.green, lineWidth: 2) } Text("Whiskers") Spacer() } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
7:24 - Custom views: view properties
struct PetRowView: View { var body: some View { HStack { profileImage Text("Whiskers") Spacer() } } private var profileImage: some View { Image(whiskers.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(.green, lineWidth: 2) } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
7:34 - Custom views: complete row view
struct PetRowView: View { var body: some View { HStack { profileImage VStack(alignment: .leading) { Text("Whiskers") Text("Tightrope walking") .font(.subheadline) .foregroundStyle(.secondary) } Spacer() } } private var profileImage: some View { Image(whiskers.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(.green, lineWidth: 2) } } } let whiskers = Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers") struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String init(_ name: String, kind: Kind, trick: String, profileImage: String) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage } }
-
7:41 - Custom views: input properties
struct PetRowView: View { var pet: Pet var body: some View { HStack { profileImage VStack(alignment: .leading) { Text(pet.name) Text(pet.trick) .font(.subheadline) .foregroundStyle(.secondary) } Spacer() } } private var profileImage: some View { Image(pet.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(pet.favoriteColor, lineWidth: 2) } } } struct Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } let id = UUID() var name: String var kind: Kind var trick: String var profileImage: String var favoriteColor: Color init(_ name: String, kind: Kind, trick: String, profileImage: String, favoriteColor: Color) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage self.favoriteColor = favoriteColor } }
-
7:53 - Custom views: reuse
PetRowView(pet: model.pet(named: "Whiskers")) PetRowView(pet: model.pet(named: "Roofus")) PetRowView(pet: model.pet(named: "Bubbles"))
-
7:59 - List composition
struct ContentView: View { var model: PetStore var body: some View { List(model.allPets) { pet in PetRowView(pet: pet) } } } @Observable class PetStore { var allPets: [Pet] = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green), Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue), Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange), Pet("Mango", kind: .bird, trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green), Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple), Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown), Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange) ] }
-
8:14 - List composition: ForEach
struct ContentView: View { var model: PetStore var body: some View { List { ForEach(model.allPets) { pet in PetRowView(pet: pet) } } } } @Observable class PetStore { var allPets: [Pet] = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green), Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue), Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange), Pet("Mango", kind: .bird, trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green), Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple), Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown), Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange) ] }
-
8:27 - List composition: sections
struct ContentView: View { var model: PetStore var body: some View { List { Section("My Pets") { ForEach(model.myPets) { pet in PetRowView(pet: pet) } } Section("Other Pets") { ForEach(model.otherPets) { pet in PetRowView(pet: pet) } } } } } @Observable class PetStore { var myPets: [Pet] = [ Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue), Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown), ] var otherPets: [Pet] = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green), Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange), Pet("Mango", kind: .bird, trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green), Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple), Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange) ] }
-
8:36 - List composition: section actions
PetRowView(pet: pet) .swipeActions(edge: .leading) { Button("Award", systemImage: "trophy") { // Give pet award } .tint(.orange) ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name))) }
-
9:31 - View updates
struct ContentView: View { var model: PetStore var body: some View { List { Section("My Pets") { ForEach(model.myPets) { pet in row(pet: pet) } } Section("Other Pets") { ForEach(model.otherPets) { pet in row(pet: pet) } } } } private func row(pet: Pet) -> some View { PetRowView(pet: pet) .swipeActions(edge: .leading) { Button("Award", systemImage: "trophy") { pet.giveAward() } .tint(.orange) ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name))) } } } struct PetRowView: View { var pet: Pet var body: some View { HStack { profileImage VStack(alignment: .leading) { HStack(alignment: .firstTextBaseline) { Text(pet.name) if pet.hasAward { Image(systemName: "trophy.fill") .foregroundStyle(.orange) } } Text(pet.trick) .font(.subheadline) .foregroundStyle(.secondary) } Spacer() } } private var profileImage: some View { Image(pet.profileImage) .clipShape(.circle) .shadow(radius: 3) .overlay { Circle().stroke(pet.favoriteColor, lineWidth: 2) } } } @Observable class PetStore { var myPets: [Pet] = [ Pet("Roofus", kind: .dog, trick: "Home runs", profileImage: "Roofus", favoriteColor: .blue), Pet("Sheldon", kind: .turtle, trick: "Kickflip", profileImage: "Sheldon", favoriteColor: .brown), ] var otherPets: [Pet] = [ Pet("Whiskers", kind: .cat, trick: "Tightrope walking", profileImage: "Whiskers", favoriteColor: .green), Pet("Bubbles", kind: .fish, trick: "100m freestyle", profileImage: "Bubbles", favoriteColor: .orange), Pet("Mango", kind: .bird, trick: "Basketball dunk", profileImage: "Mango", favoriteColor: .green), Pet("Ziggy", kind: .lizard, trick: "Parkour", profileImage: "Ziggy", favoriteColor: .purple), Pet("Chirpy", kind: .bug, trick: "Canon in D", profileImage: "Chirpy", favoriteColor: .orange) ] } @Observable class Pet: Identifiable { enum Kind { case cat case dog case fish case bird case lizard case turtle case rabbit case bug var systemImage: String { switch self { case .cat: return "cat.fill" case .dog: return "dog.fill" case .fish: return "fish.fill" case .bird: return "bird.fill" case .lizard: return "lizard.fill" case .turtle: return "tortoise.fill" case .rabbit: return "rabbit.fill" case .bug: return "ant.fill" } } } var name: String var kind: Kind var trick: String var profileImage: String var favoriteColor: Color var hasAward: Bool = false init(_ name: String, kind: Kind, trick: String, profileImage: String, favoriteColor: Color) { self.name = name self.kind = kind self.trick = trick self.profileImage = profileImage self.favoriteColor = favoriteColor } func giveAward() { hasAward = true } } extension Pet: Transferable { static var transferRepresentation: some TransferRepresentation { ProxyRepresentation { $0.name } } }
-
10:57 - State changes
struct RatingView: View { @State var rating: Int = 5 var body: some View { HStack { Button("Decrease", systemImage: "minus.circle") { rating -= 1 } .disabled(rating == 0) .labelStyle(.iconOnly) Text(rating, format: .number.precision(.integerLength(2))) .font(.title.bold()) Button("Increase", systemImage: "plus.circle") { rating += 1 } .disabled(rating == 10) .labelStyle(.iconOnly) } } }
-
11:51 - State changes: animation
struct RatingView: View { @State var rating: Int = 5 var body: some View { HStack { Button("Decrease", systemImage: "minus.circle") { withAnimation { rating -= 1 } } .disabled(rating == 0) .labelStyle(.iconOnly) Text(rating, format: .number.precision(.integerLength(2))) .font(.title.bold()) Button("Increase", systemImage: "plus.circle") { withAnimation { rating += 1 } } .disabled(rating == 10) .labelStyle(.iconOnly) } } }
-
12:05 - State changes: text content transition
struct RatingView: View { @State var rating: Int = 5 var body: some View { HStack { Button("Decrease", systemImage: "minus.circle") { withAnimation { rating -= 1 } } .disabled(rating == 0) .labelStyle(.iconOnly) Text(rating, format: .number.precision(.integerLength(2))) .contentTransition(.numericText(value: Double(rating))) .font(.title.bold()) Button("Increase", systemImage: "plus.circle") { withAnimation { rating += 1 } } .disabled(rating == 10) .labelStyle(.iconOnly) } } }
-
12:22 - State changes: multiple state
struct RatingContainerView: View { @State private var rating: Int = 5 var body: some View { Gauge(value: Double(rating), in: 0...10) { Text("Rating") } RatingView() } } struct RatingView: View { @State var rating: Int = 5 var body: some View { HStack { Button("Decrease", systemImage: "minus.circle") { withAnimation { rating -= 1 } } .disabled(rating == 0) .labelStyle(.iconOnly) Text(rating, format: .number.precision(.integerLength(2))) .contentTransition(.numericText(value: Double(rating))) .font(.title.bold()) Button("Increase", systemImage: "plus.circle") { withAnimation { rating += 1 } } .disabled(rating == 10) .labelStyle(.iconOnly) } } }
-
12:45 - State changes: state and binding
struct RatingContainerView: View { @State private var rating: Int = 5 var body: some View { Gauge(value: Double(rating), in: 0...10) { Text("Rating") } RatingView(rating: $rating) } } struct RatingView: View { @Binding var rating: Int var body: some View { HStack { Button("Decrease", systemImage: "minus.circle") { withAnimation { rating -= 1 } } .disabled(rating == 0) .labelStyle(.iconOnly) Text(rating, format: .number.precision(.integerLength(2))) .contentTransition(.numericText(value: Double(rating))) .font(.title.bold()) Button("Increase", systemImage: "plus.circle") { withAnimation { rating += 1 } } .disabled(rating == 10) .labelStyle(.iconOnly) } } }
-
14:16 - Adaptive buttons
Button("Reward", systemImage: "trophy") { // Give pet award } // .buttonStyle(.borderless) // .buttonStyle(.bordered) // .buttonStyle(.borderedProminent)
-
14:53 - Adaptive toggles
Toggle("Nocturnal Mode", systemImage: "moon", isOn: $pet.isNocturnal) // .toggleStyle(.switch) // .toggleStyle(.checkbox) // .toggleStyle(.button)
-
15:19 - Searchable
struct PetListView: View { @Bindable var viewModel: PetStoreViewModel var body: some View { List { Section("My Pets") { ForEach(viewModel.myPets) { pet in row(pet: pet) } } Section("Other Pets") { ForEach(viewModel.otherPets) { pet in row(pet: pet) } } } .searchable(text: $viewModel.searchText) } private func row(pet: Pet) -> some View { PetRowView(pet: pet) .swipeActions(edge: .leading) { Button("Reward", systemImage: "trophy") { pet.giveAward() } .tint(.orange) ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name))) } } } @Observable class PetStoreViewModel { var petStore: PetStore var searchText: String = "" init(petStore: PetStore) { self.petStore = petStore } var myPets: [Pet] { // For illustration purposes only. The filtered pets should be cached. petStore.myPets.filter { searchText.isEmpty || $0.name.contains(searchText) } } var otherPets: [Pet] { // For illustration purposes only. The filtered pets should be cached. petStore.otherPets.filter { searchText.isEmpty || $0.name.contains(searchText) } } }
-
15:20 - Searchable: customization
struct PetListView: View { @Bindable var viewModel: PetStoreViewModel var body: some View { List { Section("My Pets") { ForEach(viewModel.myPets) { pet in row(pet: pet) } } Section("Other Pets") { ForEach(viewModel.otherPets) { pet in row(pet: pet) } } } .searchable(text: $viewModel.searchText, editableTokens: $viewModel.searchTokens) { $token in Label(token.kind.name, systemImage: token.kind.systemImage) } .searchScopes($viewModel.searchScope) { Text("All Pets").tag(PetStoreViewModel.SearchScope.allPets) Text("My Pets").tag(PetStoreViewModel.SearchScope.myPets) Text("Other Pets").tag(PetStoreViewModel.SearchScope.otherPets) } .searchSuggestions { PetSearchSuggestions(viewModel: viewModel) } } private func row(pet: Pet) -> some View { PetRowView(pet: pet) .swipeActions(edge: .leading) { Button("Reward", systemImage: "trophy") { pet.giveAward() } .tint(.orange) ShareLink(item: pet, preview: SharePreview("Pet", image: Image(pet.name))) } } }
-
16:58 - App definition
@main struct SwiftUIEssentialsApp: App { var body: some Scene { WindowGroup { ContentView() } } }
-
17:15 - App definition: multiple scenes
@main struct SwiftUIEssentialsApp: App { var body: some Scene { WindowGroup { ContentView() } WindowGroup("Training History", id: "history", for: TrainingHistory.ID.self) { $id in TrainingHistoryView(historyID: id) } WindowGroup("Pet Detail", id: "detail", for: Pet.ID.self) { $id in PetDetailView(petID: id) } } }
-
17:23 - Widgets
struct ScoreboardWidget: Widget { var body: some WidgetConfiguration { // ... } } struct ScoreboardWidgetView: View { var petTrick: PetTrick var body: some View { ScoreCard(rating: petTrick.rating) .overlay(alignment: .bottom) { Text(petTrick.pet.name) .padding() } .widgetURL(petTrick.pet.url) } }
-
19:37 - Digital Crown rotation
ScoreCardStack(rating: $rating) .focusable() #if os(watchOS) .digitalCrownRotation($rating, from: 0, through: 10) #endif
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。