[iOS][Weekly] 2021/11/19
2021.12.02
[iOS][Weekly] 2021/11/19
본문
내용
⭐️ NEWS ⭐️
1. Swift 빌드가 더 빨라졌다
- Xcode 13.2 beta가 공개되었다.
- 빌드 시스템이 개선되었다.
⭐️ CODE ⭐️
1. (오픈소스) SwiftUI-Navigation에 대해 알아보자
기존 Navigation 뷰의 문제점
- 현재 SwiftUI에서 지원하는 내비게이션 형태의 뷰 (alert, sheet, navigation links 등)에는 몇가지 문제점이 있다.
- SwiftUI에서 시트창을 열고 싶으면 아래처럼 열어야 한다.
struct ContentView: View {
@State var draft: Post?
var body: some View {
Button("Edit") {
self.draft = Post()
}
.sheet(item: self.$draft) { (draft: Post) in
EditPostView(post: draft)
}
}
}
draft
라는 optional value가 있고, draft가 non-nil 일 경우 sheet 뷰를 출력한다.- 하지만, 이때 치명적인 단점이 있는데 그것은 sheet 뷰가 열릴 때 클로저로 전달되는 draft가 바인딩 타입이 아니다.
- 즉,
EditPostView
에서 draft를 수정해도 기존 뷰(ContentView
)의 draft에는 영향이 가지 않는다. -> 즉, 화면 업데이트가 되지 않는다. - 또 다른 문제를 보자.
.sheet(item: self.$draft) { (draft: Post) in
EditPostView(post: draft)
}
.sheet(item: self.$settings) { (settings: Settings) in
SettingsView(settings: settings)
}
.sheet(item: self.$userProfile) { (userProfile: Profile) in
UserProfile(profile: userProfile)
}
draft
가 non-nil 일 경우EditPostView
를,settings
가 non-nil일 경우SettingsView
를,userProfile
이 non-nil일 경우UserProfile
을 출력하고 싶을 때 이렇게 작성할 수 있겠지만 이를 관리하기는 쉽지 않다.- 3개의 optional value가 있기 때문에 가능한 상황은 총 8가지(2^3) 이고, 그중 4가지는 문제가 있다.
draft | settings | userProfile | 예상 동작 |
---|---|---|---|
nil | nil | nil | 아무 동작 안함 |
non-nil | nil | nil | EditPostView 출력 |
nil | non-nil | nil | SettingsView 출력 |
nil | nil | non-nil | UserProfile 출력 |
non-nil | non-nil | nil | EditPostView 출력 &SettingsView 출력 |
non-nil | nil | non-nil | EditPostView 출력 &UserProfile 출력 |
nil | non-nil | non-nil | SettingsView 출력 &UserProfile 출력 |
non-nil | non-nil | non-nil | EditPostView 출력 &SettingsView 출력 &UserProfile 출력 |
- 4가지 상황이 발생하지 않도록 사용자는 상당한 주의가 필요하게 된다.
- 요런 여러가지 불편사항들을 개선하기 위해 Swift-Navigation 오픈소스를 만들었다고 한다. 한번 알아보자.
Swift-Navigation 알아보기
- 오픈소스
- 위에서 살펴본 여러가지 상태를 컨트롤해야 하는 상황을 위해서 enum을 활용해준다.
- enum 변수를 바인딩 형태로 넘겨주고 또한 클로저로 enum 파라미터의 바인딩 타입이 오는 것을 눈여겨 보자.
enum Route {
case draft(Post)
case settings(Settings)
case userProfile(Profile)
}
...
@State var route: Route?
...
.sheet(unwrapping: self.$route, case: /Route.draft) { $draft in
EditPostView(post: $draft)
}
.sheet(unwrapping: self.$route, case: /Route.settings) { $settings in
SettingsView(settings: $settings)
}
.sheet(unwrapping: self.$route, case: /Route.userProfile) { $userProfile in
UserProfile(profile: $userProfile)
}
Switch
,IfCaseLet
,CaseLet
,IfLet
등 API도 있다.- 상태에 따라 출력해야할 뷰가 다를 경우
Switch
과CaseLet
API를 사용해서 바인딩 타입을 전달받아서 적절하게 처리도 가능하다.
enum ItemStatus {
case inStock(quantity: Int)
case outOfStock(isOnBackorder: Bool)
}
struct InventoryItemView {
@State var status: ItemStatus?
var body: some View {
Switch(self.$status) {
CaseLet(/ItemStatus.inStock) { $quantity in // <- enum 파라미터가 binding 형태로 내려온다.
HStack {
Text("Quantity: \(quantity)")
Stepper("Quantity", value: $quantity)
}
Button("Out of stock") { self.status = .outOfStock(isOnBackorder: false) }
}
CaseLet(/ItemStatus.outOfStock) { $isOnBackorder in
Toggle("Is on back order?", isOn: $isOnBackorder)
Button("In stock") { self.status = .inStock(quantity: 1) }
}
}
}
}
댓글남기기