스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
watchOS 10용으로 앱 업데이트하기
watchOS 10의 최신 기능을 활용할 수 있도록 Apple Watch 앱을 함께 업데이트해 봅니다. 이번 코딩 세션에서는 한눈에 앱을 파악하기 쉽도록 최신 SwiftUI API를 사용하고 Digital Crown을 중심으로 앱 탐색 방향을 재설정하는 방법을 다룹니다.
챕터
- 1:33 - Build against the watchOS 10 SDK
- 2:33 - NavigationSplitView
- 5:21 - TabView and vertical pagination
- 8:11 - Toolbar with new placement options
- 9:07 - Background color
- 11:10 - Materials
리소스
관련 비디오
WWDC23
-
다운로드
♪ ♪
안녕하세요 watchOS 소프트웨어 엔지니어 니나 파리포비치입니다 이번 코딩 세션에서는 watchOS 9 SDK로 제작된 기존 앱을 watchOS 10용으로 업데이트해 보겠습니다 앱을 보기 좋게 만들고 전 시스템을 재디자인하도록 새로운 디자인 패러다임과 SwiftUI API를 살펴볼게요 샘플 프로젝트는 이번 세션과 연결된 자료 목록에 링크를 걸어 뒀어요 지금 바로 다운로드하셔서 watchOS 10을 함께 빌드해 보시길 바라요 본격적으로 시작하기에 앞서 기존 프로젝트를 살펴봅시다 이번 시간에 업데이트할 앱은 Backyard Birds입니다 아름다운 뒤뜰 정원과 호기심 가득한 방문객 친구들을 생성하고 관리하는 앱이죠 현재 앱에는 뒤뜰 목록이 있습니다 각 뒤뜰의 디테일 뷰에서 활동과 상태를 보여 줍니다 음식이나 물이 부족하면 채워 줄 수 있고 각 뒤뜰을 방문하는 새도 볼 수 있어요 watchOS 10은 Watch 앱에 재밌고 신선한 모습을 선사합니다 아직 확인해 보지 못했다면 'watchOS 10 알아보기' 'watchOS 10 앱 디자인하고 빌드하기' 두 세션을 시청하고 이번 세션에 적용해 볼 디자인 원칙을 알아보세요 이제 Xcode를 열어서 앱 업데이트를 시작해 봅시다
현재 Backyard Birds 앱은 watchOS 9용으로 빌드하고 실행됐습니다 뒤뜰 목록을 클릭하면 디테일이 나오는데요 watchOS10 SDK로 빌드해 봅시다
앱은 지금도 근사합니다 새로운 시스템 기능을 확인할 수 있는데요 제목은 스크롤 시 큰 글씨로 전환되고 탐색 막대 아래 콘텐츠를 블러 처리 하는 새 머티리얼도 눈에 띕니다 뒤뜰을 탭하면 셀이 애니메이팅되고 시스템 전체에 자동으로 적용된 도구 막대 버튼 스타일링이 왼쪽 상단에 있군요 아래로 스크롤해서 리필하기 버튼을 누르면 모달이 나오는데 흐릿한 백그라운드 머티리얼이 새로 적용된 상태입니다
Backyard Birds 사용자의 가장 큰 관심사는 본인 뒤뜰의 상황입니다 현재 사용자는 앱을 시작하면 가장 먼저 목록에서 뒤뜰을 눌러 디테일 뷰를 들여다봅니다 watchOS 10에서는 NavigationSplitView로 앱의 구조를 변경해 사용이 좀 더 용이해졌습니다 뒤뜰의 디테일 뷰로 곧바로 접속했다가 원한다면 목록으로 돌아가 친구의 뒤뜰에 방문하는 방식이죠 Backyard Birds 앱의 핵심은 디테일 뷰이기 때문에 NavigationSplitView를 구현해 이를 강조할 수 있습니다
NavigationSplitView는 강력한 소스 목록과 세부 사항 관계가 있을 때 유용합니다 곧바로 디테일 뷰에 접속해 세부 사항을 살피도록 하고 소스 목록에서 다른 뒤뜰로 이동하기도 쉽죠
iOS와 iPadOS에서는 Backyard Birds에 이미 사용하고 있습니다 NavigationSplitView가 앱에 아주 적합한 것 같군요
ContentView에서 NavigationStack을 NavigationSplitView로 바꿔 줄 겁니다 그런 다음 navigationDestination의 콘텐츠를 NavigationSplitView의 세부 사항으로 옮겨 주고요 마지막으로 watchOS 10에서 사용 가능한 새로운 목록 선택 API를 채택하고 NavigationSplitView에서 표시할 디테일 뷰를 선택해 구동할 겁니다 우선 NavigationStack을 NavigationSplitView로 바꿔 봅시다
뒤뜰 목록은 원래 위치 그대로 NavigationSplitView 하단에 남겨 두겠습니다 navigationDestination 수정자는 없애 버리고 BackyardView를 디테일 뷰 빌더로 옮길게요 selectedBackyard는 선택적이므로 언래핑하고 폴백 뷰를 제공합시다
마지막으로 selection 바인딩을 취하는 목록 이니셜라이저를 사용합니다 목록의 selection 매개변수에 값을 제공할 때 selection 바인딩이 NavigationSplitView 내에서 어떤 디테일 뷰를 표시할지 선택해서 구동하죠
좋아요 선택한 뒤뜰의 디테일 뷰가 이제 자동으로 나오는군요 세부 사항을 바로 시작하므로 navigationTitle은 없애도 되겠어요 나머지 뒤뜰을 보러 다시 이동할 수도 있습니다 여기 보이는 소스 리스트 버튼으로요 다시 탭해서 디테일 뷰로 들어가면 전체 화면 애니메이션이 근사하게 작동하네요 지금 뒤뜰 뷰는 스크롤 가능한 콘텐츠로 구성된 긴 목록으로 구성돼 있습니다 목록은 이미 서로 다른 기능이 있는 세 섹션으로 나뉘어 있습니다 각각 오늘 뷰와 서식지 뷰 그리고 방문객 뷰인데요 앱의 시각적 명료성을 향상하려면 TabView를 대신 사용하고 섹션별로 탭을 생성하면 되죠
TabView는 콘텐츠를 전체 화면 뷰로 분할하는 방법을 제시하며 각 탭은 명확하고 뚜렷한 목적이 있습니다 Digital Crown 기능은 그대로 두겠습니다 뷰를 빠르게 스크롤할 수 있도록요 새로운 수직 페이지 스타일 덕에 TabView로 이런 설정이 가능하죠 탭에서 탭으로 빠르게 이동하고 한 탭 내에서 스크롤하는 것도 가능해요
Xcode로 되돌아가서 TabView를 사용할 수 있도록 디테일 뷰를 업데이트해 볼게요
BackyardView에서 각 섹션을 해당 뷰로 이동하고 List를 TabView로 바꿔 줍시다 TabView의 각 페이지가 화면 전체를 차지하므로 섹션과 디바이더는 필요 없겠죠 섹션 헤더를 navigationTitle에 다시 추가하도록 합시다
마지막으로 tabViewStyle 수정자를 사용해 verticalPage가 필요하다고 명시해 보죠 거의 다 됐습니다 페이지를 매기면서 보니 탭마다 뷰가 들어가 있습니다 모든 방문객을 빠르게 확인하고 싶다면 List에서 VisitorView를 랩핑해 주세요
이제 TabView가 탭을 자식 List 뷰에 지정할 겁니다 목록이 화면 높이를 초과한다면 뷰를 스크롤할 수 있습니다
수직 TabView에 스크롤 가능한 콘텐츠가 있다면 되도록 마지막 탭으로 배치하세요
서식지 뷰도 두 탭으로 분할해 보겠습니다 음식과 물 레벨을 쉽게 구별할 수 있도록요
이를 위해 TabView에 더 잘 어울리도록 게이지를 생성해 봤어요
TabView에서 HabitatView를 새 GaugeView로 바꿔 줄게요 음식과 물에 대한 인스턴스를 하나씩 생성하는 방식으로요
보기에 괜찮네요 이제 리필 기능만 다시 추가하면 됩니다 도구 막대를 사용할게요 도구 막대는 watchOS 10에서 향상되었습니다 새로운 배치 옵션이 생겼는데 모든 화면 크기에서 일관되게 설계되었습니다 새로운 하단 막대 배치는 컨트롤을 배치하기 좋은 곳이죠 하단 막대에 리필하기 버튼을 추가해 이런 배치 옵션을 활용해 보고자 합니다
새 HabitatGaugeView에서 도구 막대를 추가하고 ToolbarGroup을 사용해 하단 막대 배치를 명시합니다 스페이서를 사용해서 도구 막대 뒤쪽 모서리에 버튼을 추가할게요
공간이 훨씬 많이 생겼고 서식지 요약에 집중하기가 훨씬 수월해졌습니다 TabView에서 이동할 때 도움이 되도록 추가 작업을 진행해 볼게요 또한 뒤뜰에서 음식과 물이 부족할 때 주의를 줄 수 있도록 설정하고 싶습니다 백그라운드 그러데이션을 적용하면 됩니다 탭에 제목을 붙여도 되지만 색을 활용하는 게 좋습니다 한눈에 파악하기 쉽고 디테일 뷰 내에서 현재 위치를 강화할 수 있으니까요 음식이나 물이 부족할 때 뒤뜰 상태를 강조하도록 사용할 수도 있겠죠 시스템 그러데이션은 포그라운드 요소와 대비를 유지하면서 이를 전달하기에 좋습니다 해당 내용을 달성할 수 있도록 색상 그러데이션과 함께 컨테이너 백그라운드 수정자를 사용해 봅시다 기존 백그라운드를 제거하고 음식과 물 레벨에 따라 백그라운드 색을 결정하는 함수를 BackyardView에 추가할게요 물과 음식이 부족하면 백그라운드가 빨간색으로 바뀌면서 리필할 때가 됐다는 걸 알려 줍니다 유용한 연산 변수도 몇 가지 추가해 보죠 이제 이런 연산 프로퍼티를 containerBackground 수정자로 전달합니다
수정자는 색상 그러데이션을 전달할 ShapeStyle과 ContainerBackgroundPlacement를 받아들입니다 TabView용이라고 여기에 명시할게요
백그라운드 색이 바뀔 때 게이지 색도 바뀌면 좋겠네요 동일한 연산 색상 변수를 전달해 봅시다
앱의 악센트 컬러를 사용해 TabView 내 다른 뷰에 containerBackground 수정자를 적용하겠습니다
스크롤하며 살펴보니 그러데이션이 포그라운드 요소와 잘 대비되는군요 도구 막대 버튼을 탭하면 백그라운드 그러데이션이 바뀝니다
마지막으로 중요한 정보를 강조할 수 있도록 머티리얼을 활용해 보겠습니다 머티리얼은 여러 플랫폼에서 사용 가능해졌고 watchOS10에서 앱을 새롭게 보여주는 기능입니다
포그라운드 요소와 백그라운드 요소를 구별하고 시각적 화려함을 더하는 유용한 방법인데요 또한 화면에 정보를 표시하거나 강화합니다 머티리얼을 적용하고 생동감을 줄 수 있는 앱 내 공간이 몇 군데 있어요 함께 살펴보시죠 먼저 뒤뜰 명칭의 그림자 배경을 머티리얼 백그라운드로 바꾸고자 합니다 셀의 백그라운드는 다채로우니까 머티리얼을 추가하면 명칭이 선명해질 겁니다
사람들이 관심을 많이 두는 뒤뜰의 방문객 수는 요약 뷰에서 확인할 수 있는데요 목록 뷰에도 수를 표시하면 좋겠네요 뒤뜰의 디테일 뷰에 들어가지 않고도 방문객 수를 알 수 있도록요 또 다른 오버레이로 추가하고 머티리얼 백그라운드를 숫자에 제공하겠습니다 watchOS 앱은 주로 다크 백그라운드를 사용합니다 그래서 머티리얼이 다크 변형으로 기본 설정 돼 있죠 뒤뜰의 색이 밝고 다채롭기 때문에 라이트 변형으로 바꿔 줄게요
이렇게 Backyard Birds 앱을 watchOS 10용으로 업데이트해 봤습니다
주요 변경 사항을 살펴보죠 NavigationSplitView를 목록에 추가했고 List를 수직 TabView로 바꿔 줬습니다 뒤뜰마다 도구 막대에 기능을 추가했고 근사하게 그러데이션도 넣었죠 머티리얼을 사용해 유용한 정보도 표시해 봤고요 오늘 코딩 시간에 함께해 주셔서 감사합니다 올해는 Apple Watch에 뜻깊은 해입니다 더 많은 세션을 시청해 보시길 바라요 Backyard Birds가 더 궁금하시다면 이 세션을 추천할게요 'Apple Watch에서 스마트 스택용 위젯 빌드하기' watchOS 10에서 여러분의 앱이 빛날 수 있도록 업데이트해 보시길 바랍니다
-
-
4:02 - NavigationSplitView
NavigationSplitView { List(backyardsData.backyards, selection: $selectedBackyard) { backyard in BackyardCell(backyard: backyard) } .listStyle(.carousel) } detail: { if let selectedBackyard { BackyardView(backyard: selectedBackyard) } else { BackyardUnavailableView() } }
-
6:18 - Vertical TabView
TabView { TodayView() .navigationTitle("Today") HabitatGaugeView(level: $waterLevel, habitatType: .water, tintColor: .blue) .navigationTitle("Water") HabitatGaugeView(level: $foodLevel, habitatType: .food, tintColor: .green) .navigationTitle("Food") List { VisitorView() .navigationTitle("Visitors") } } .tabViewStyle(.verticalPage)
-
8:37 - Add refill button to Toolbar
.toolbar { ToolbarItemGroup(placement: .bottomBar) { Spacer() Button { level = Int(min(100, Double(level) + 5)) } label: { Label("Add", systemImage: "plus") } } }
-
9:48 - HabitatGaugeView background color function and variables
func backgroundColor(_ level: Int, for type: HabitatType) -> Color { let color: Color = type == .food ? .green : .blue return level < 40 ? .red : color } var waterColor: Color { backgroundColor(waterLevel, for: .water) } var foodColor: Color { backgroundColor(foodLevel, for: .food) }
-
10:10 - .containerBackground within TabView
TabView { TodayView() .navigationTitle("Today") .containerBackground(Color.accentColor.gradient, for: .tabView) HabitatGaugeView(level: $waterLevel, habitatType: .water, tintColor: waterColor) .navigationTitle("Water") .containerBackground(waterColor.gradient, for: .tabView) HabitatGaugeView(level: $foodLevel, habitatType: .food, tintColor: foodColor) .navigationTitle("Food") .containerBackground(foodColor.gradient, for: .tabView) List { VisitorView() .navigationTitle("Visitors") .containerBackground(Color.accentColor.gradient, for: .tabView) } } .tabViewStyle(.verticalPage) .environmentObject(backyard) .navigationTitle(backyard.displayName)
-
11:38 - Add material to the backyard name
.foregroundStyle(.secondary) .background(Material.ultraThin, in: RoundedRectangle(cornerRadius: 7))
-
12:15 - Visitor score overlay with materials
.overlay(alignment: .topTrailing) { Text("\(backyard.visitorScore)") .frame(width: 25, height: 25) .foregroundStyle(.secondary) .background(.ultraThinMaterial, in: .circle) .padding(.top, 5) }
-
12:20 - Light materials
.environment(\.colorScheme, .light)
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.