오늘은 SwiftUI에서 UserDefault인 @AppeStorage에 대해서 알아보겠습니다.
우리가 SwiftUI로 앱을 구성하다보면, 앱 프로젝트 전체범위에서 접근 가능한 데이터가 필요할 때가 있죠. 예를들면, 다음과 같은 것들 입니다.
- 사용자가 앱을 처음으로 켰는지 여부 -> Onboarding 화면을 보여준다.
- 사용자가 서버에서 받은 JWT -> 네트워크통신을 할 때, 데이터를 헤더에 함께 전달해준다.
- 앱의 전체에 적용되는 TintColor -> 사용자가 선택한 색상으로 일괄적으로 UI색상을 변경한다.
물론 다른 해결방법으로도 해결 가능합니다. 서브클래싱을 통해서 데이터를 전달할 수도 있고, 프로토콜에 extension + computed Property를 활용할 수도 있죠. 여러 가지 해결방법 중에서 이번에는 @AppStorage
를 통해서 해결해보겠습니다.
(물론 JWT같은 데이터는 개인정보에 접근이 가능한 데이터이므로, 가능하면 저장하지 않는게 좋겠죠? 예시를 위한 예시입니다.)
다음과 같은 뷰가 있다고 합시다.
AppStorage는 다음과 같이 초기화했습니다.
@AppStorage("username") var username = "Moya"
...
Text("사용자 이름:")
.font(.system(size: 20, weight: .medium, design: .rounded))
Text("\(username)").bold()
그리고 상세화면입니다.
@AppStorage("username") var username: String!
@State private var newUsername = ""
...
TextField("이름", text: $newUsername)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.horizontal)
...
Button("업데이트") {
username = newUsername
}
그러면 다음과 같이 정상적으로 저장됩니다.
이렇게 AppStorage를 사용할 수 있습니다. 다만 이런 의문이 듭니다.
AppStorage 변경을 버튼을 통해서 말고 Binding은 안되나??
가능합니다. 코드를 수정할게요.
//@AppStorage("username") var username: String!
@Binding var username: String
//@State private var newUsername = ""
...
//TextField("이름", text: $newname)
TextField("이름", text: $username)
NavigationLink("Edit", destination: AppStorage_Edit(username: $username))
이번에는 버튼을 없애도 이렇게 바로 업데이트 되고 있죠?
AppStorage의 저장되는 위치를 설명하기 위해, App - Scenes - Views 의 관계도를 보겠습니다.
(한땀한땀만듦)
이 구조를 한 번 코드로 보겠습니다.
import SwiftUI
@main
struct AppStorage_ExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
AppStorage는 말그대로 App 위치에 저장되는 저장소입니다, UIKit에서 자주사용하던, UserDefault 의 SwiftUI 버전입니다. 그래서 이 위치에 데이터를 저장하면, 프로젝트 전역범위에서 접근 가능한 데이터를 보관할 수 있죠.
공식문서의 AppStore설명을 보면 다음과 같습니다.
AppStorage의 개념은 저장소의 의미 외에는 딱히 없다고 생각됩니다.
저장소니까 두 가지로 나눠서 생각할 수 있겠네요
읽어주셔서 감사합니다.