Streaming is available in most browsers,
and in the Developer app.
-
Demystify SwiftUI containers
Learn about the capabilities of SwiftUI container views and build a mental model for how subviews are managed by their containers. Leverage new APIs to build your own custom containers, create modifiers to customize container content, and give your containers that extra polish that helps your apps stand out.
Chapters
- 0:00 - Introduction
- 3:17 - Composition
- 10:42 - Sections
- 13:18 - Customization
- 16:52 - Next steps
Resources
Related Videos
WWDC23
WWDC21
-
DownloadArray
-
-
0:20 - SwiftUI Lists
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") }
-
0:36 - SwiftUI Lists
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(otherSongs) { song in Text(song.title) } }
-
0:54 - SwiftUI Lists
List { Section("Favorite Songs") { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } Section("Other Songs") { ForEach(otherSongs) { song in Text(song.title) } } }
-
1:00 - SwiftUI Lists
List { Section("Favorite Songs") { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } Section("Other Songs") { ForEach(otherSongs) { song in Text(song.title) .listRowSeparator(.hidden) } } }
-
2:35 - Data-driven DisplayBoard
@State private var songs: [Song] = [ Song("Scrolling in the Deep"), Song("Born to Build & Run"), Song("Some Body Like View"), ] var body: some View { DisplayBoard(songs) { song in Text(song.title) } }
-
2:47 - DisplayBoard implementation
// Insert code snvar data: Data @ViewBuilder var content: (Data.Element) -> Content var body: some View { DisplayBoardCardLayout { ForEach(data) { item in CardView { content(item) } } } .background { BoardBackgroundView() } }
-
3:08 - Data-driven DisplayBoard
@State private var songs: [Song] = [ Song("Scrolling in the Deep"), Song("Born to Build & Run"), Song("Some Body Like View"), ] var body: some View { DisplayBoard(songs) { song in Text(song.title) } }
-
3:30 - List composition
List(songsFromSam) { song in Text(song.title) }
-
3:46 - List composition
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") }
-
3:56 - List composition
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } List(songsFromSam) { song in Text(song.title) }
-
4:05 - List composition
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } List { ForEach(songsFromSam) { song in Text(song.title) } }
-
4:24 - List composition
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
4:59 - DisplayBoard implementation
var data: Data @ViewBuilder var content: (Data.Element) -> Content var body: some View { DisplayBoardCardLayout { ForEach(data) { item in CardView { content(item) } } } .background { BoardBackgroundView() } }
-
5:15 - DisplayBoard implementation
// DisplayBoard implementation @ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { ForEach(data) { item in CardView { content(item) } } } .background { BoardBackgroundView() } } DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } DisplayBoard { ForEach(songsFromSam) { song in Text(song.title) } }
-
5:27 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { ForEach(subviewOf: content) { subview in CardView { subview } } } .background { BoardBackgroundView() } }
-
5:52 - List composition
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
5:57 - DisplayBoard composition
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
6:12 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { ForEach(subviewOf: content) { subview in CardView { subview } } } .background { BoardBackgroundView() } }
-
6:23 - DisplayBoard subviews
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
6:36 - Declared vs. resolved views
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } } // 3 resolved subviews Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") // 9 resolved subviews Text("I Container Multitudes") … Text("Love Stack")
-
7:11 - List subviews
List { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
7:19 - Declared vs. resolved views
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } } // 3 resolved subviews Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") // 9 resolved subviews Text("I Container Multitudes") … Text("Love Stack")
-
8:00 - Resolved ForEach
// 1 declared view ForEach(songsFromSam) { song in Text(song.title) } // 9 resolved subviews Text("I Container Multitudes") … Text("Love Stack")
-
8:16 - Resolved Group
// 1 declared view Group { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } // 3 resolved subviews Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View")
-
8:32 - Resolved EmptyView
// 1 declared view EmptyView() // Zero resolved subviews
-
8:39 - Resolved if expression
// Insert code snippet.
-
8:48 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { ForEach(subviewOf: content) { subview in CardView { subview } } } .background { BoardBackgroundView() } }
-
9:11 - DisplayBoard composition
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } }
-
9:17 - DisplayBoard composition
DisplayBoard { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") ForEach(songsFromSam) { song in Text(song.title) } ForEach(songsFromSommer) { song in Text(song.title) } }
-
9:44 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { ForEach(subviewOf: content) { subview in CardView { subview } } } .background { BoardBackgroundView() } }
-
9:55 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { Group(subviewsOf: content) { subviews in ForEach(subviews) { subview in CardView { subview } } } } .background { BoardBackgroundView() } }
-
10:19 - DisplayBoard implementation
@ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { Group(subviewsOf: content) { subviews in ForEach(subviews) { subview in CardView( scale: subviews.count > 15 ? .small : .normal ) { subview } } } } .background { BoardBackgroundView() } }
-
10:47 - List sections
List { Section("Favorite Songs") { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } Section("Other Songs") { ForEach(otherSongs) { song in Text(song.title) } } }
-
11:03 - DisplayBoard sections
DisplayBoard { Section("Matt's Favorites") { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } Section("Sam's Favorites") { ForEach(songsFromSam) { song in Text(song.title) } } Section("Sommer's Favorites") { ForEach(songsFromSommer) { song in Text(song.title) } } }
-
11:26 - Implementing DisplayBoard sections
DisplayBoard sections @ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { Group(subviewsOf: content) { subviews in ForEach(subviews) { subview in CardView( scale: subviews.count > 15 ? .small : .normal ) { subview } } } } .background { BoardBackgroundView() } }
-
11:35 - Implementing DisplayBoard sections
@ViewBuilder var content: Content var body: some View { DisplayBoardSectionContent { content } .background { BoardBackgroundView() } } struct DisplayBoardSectionContent<Content: View>: View { @ViewBuilder var content: Content ... }
-
11:42 - Implementing DisplayBoard sections
@ViewBuilder var content: Content var body: some View { HStack(spacing: 80) { ForEach(sectionOf: content) { section in DisplayBoardSectionContent { section.content } } } .background { BoardBackgroundView() } }
-
12:48 - Implementing DisplayBoard section headers
@ViewBuilder var content: Content var body: some View { HStack(spacing: 80) { ForEach(sectionOf: content) { section in VStack(spacing: 20) { if !section.header.isEmpty { DisplayBoardSectionHeaderCard { section.header } } DisplayBoardSectionContent { section.content } .background { BoardSectionBackgroundView() } } } } .background { BoardBackgroundView() } }
-
13:30 - List customization
List { Section("Favorite Songs") { Text("Scrolling in the Deep") Text("Born to Build & Run") Text("Some Body Like View") } Section("Other Songs") { ForEach(otherSongs) { song in Text(song.title) .listRowSeparator(.hidden) } } }
-
14:46 - Custom container values
extension ContainerValues { @Entry var isDisplayBoardCardRejected: Bool = false } extension View { func displayBoardCardRejected(_ isRejected: Bool) -> some View { containerValue(\.isDisplayBoardCardRejected, isRejected) } }
-
15:42 - Implementing DisplayBoard customization
struct DisplayBoardSectionContent<Content: View>: View { @ViewBuilder var content: Content var body: some View { DisplayBoardCardLayout { Group(subviewsOf: content) { subviews in ForEach(subviews) { subview in let values = subview.containerValues CardView( scale: (subviews.count > 15) ? .small : .normal, isRejected: values.isDisplayBoardCardRejected ) { subview } } } } } }
-
16:15 - DisplayBoard customization
DisplayBoard { Section("Matt's Favorites") { Text("Scrolling in the Deep") .displayBoardCardRejected(true) Text("Born to Build & Run") Text("Some Body Like View") } Section("Sam's Favorites") { ForEach(songsFromSam) { song in Text(song.title) .displayBoardCardRejected(song.samHasDibs) } } Section("Sommer's Favorites") { ForEach(songsFromSommer) { Text($0.title) }}} } .displayBoardCardRejected(true) }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.