이번에는 다크모드/라이트모드를 전환할 수 있는 버튼을 작업하였습니다.
UserDefault의 값을 @State처럼 반영하고 변경할 수 있게 해주는 @AppStorage 라는 것을 사용합니다.
@State는 앱이 종료되면 메모리에서 해제되는 반면, @AppStorage는 값이 저장된다는 차이가 있습니다.
@AppStorage는 iOS14+부터 지원합니다!
1. Assets에서 다크모드에서 사용될 컬러셋을 지정해줍니다. (ex: 배경색, 폰트색, 버튼색 등등)
2. 부모뷰에서 isDarkMode 변수를 만들어주고, Bool 값에 따라서 ColorScheme이 변경될 수 있는 코드를 작성합니다.
import SwiftUI
@main
struct SwiftUICoinApp: App {
생략
@AppStorage("isDarkMode") private var isDarkMode = false <-- 다크모드를 사용하나요?
var body: some Scene {
WindowGroup {
NavigationView {
생략
}
생략
.environment(\.colorScheme, isDarkMode ? .dark : .light) <-- 다크모드/라이트모드 전환
}
}
}
3. View에서 다크모드/라이트모드를 바꿔줄 수 있게 버튼을 만들어 주면 완성입니다.
import SwiftUI
struct SettingsView: View {
@AppStorage("isDarkMode") private var isDarkMode = false // UserDefault
@State private var isDark: Bool = false // 더보기 화면
생략
var body: some View {
VStack(spacing: 0) {
settingHeader
settingList
Spacer()
}
생략
// 더보기 화면이 보여지면 UserDefault의 값에 따라서 isDark의 상태를 변환시켜줍니다.
.onAppear {
if isDarkMode {
isDark = true
} else {
isDark = false
}
}
}
}
private extension SettingsView {
var settingHeader: some View {
HStack {
IconView(iconName: "chevron.left")
.onTapGesture {
presentationMode.wrappedValue.dismiss()
// 뒤로가기 버튼을 누르면 isDark 변수의 상태에 따라서 UserDefault에 적용해줍니다.
if isDark {
isDarkMode = true
} else {
isDarkMode = false
}
}
Spacer()
Text("더보기")
.font(.headline)
Spacer()
// 더보기 화면에만 적용되는 isDark 변수를 전환해줍니다.
Button {
isDark.toggle()
} label: {
IconView(iconName: isDark ? "moon.fill" : "sun.min.fill")
}
}
}
생략
}
@AppStorage 변수가 아닌 @State 변수도 포함해주었는데요.
처음에 @AppStorage만 변경을 해주었을 때 Navigation Link가 자동으로 dismiss되는 버그(?)가 발생하였습니다.
제 생각에는 UserDefault가 변경되면서 화면을 새롭게 그리게 되면서 발생하는 현상이 아닐까 싶은데..
검색해도 마땅히 해결책이 안 나와서 임시방편으로 @State 변수를 만들어서 더보기 화면의 색을 변경해주었습니다.
그 후 유저가 동작을 마치고 홈화면으로 돌아가기 위해 "뒤로가기"버튼을 누르면 UserDefault 값에 저장되도록 해주었어요.
원하던 기능은 달성할 수 있었는데 "뒤로가기" 버튼을 눌렀을 때 isDarkMode의 값이 뒤늦게 변경되니 dismiss 될 때 화면이 번쩍하는 부작용이 있습니다.
추후 다크모드를 변경할 때 쓰이는 코드들을 많이 보면서 해결해야 할 것 같아요.
@AppStorage 참고 블로그:
다크모드/라이트모드 참고 유튜브:
'Project > SwiftUI 블록와이드' 카테고리의 다른 글
[SwiftUI Project] Fatal error: Array index is out of range (0) | 2022.11.06 |
---|---|
[SwiftUI Project] 앱에서 Email 보내기 OpenURL (0) | 2022.10.27 |
[SwiftUI Project] 텍스트필드 글자 수 제한하기 (문제 해결 과정) (0) | 2022.10.19 |
[SwiftUI Project] 뉴스기사 URL 공유 버튼 만들기 (0) | 2022.10.19 |
[SwiftUI Project] 네트워크 모니터 추가하기 (유튜브 스타일) (2) | 2022.10.19 |
댓글