SwiftUI의 @AppStorage

June·2023년 2월 7일
1

SwiftUI-Data

목록 보기
4/12
post-thumbnail

AppStorage

  • 소량의 데이터 앱에 저장시 사용
  • 앱 종료 후에도 데이터 유지됨
  • 변수에 새 값을 할당하면 값 업데이트 됨
  • 현재 Bool, Int, Double, String, URL, Data 타입 저장 가능
  • 이외의 타입 저장 시도시 해당 오류 발생 : “No exact matches in call to initializer”
  • 기본값은 AppStorage 키와 타입 연결에 사용됨.
// AppStorage에 username이라는 키 제공 
@AppStorage("username") var username = "June"
import SwiftUI

struct whatIsAppStorage: View {
    
    @AppStorage("username") var username: String!   // 동일한 키를 사용해 동일한 AppStorage값 액세스
    @State private var newUsername = ""
    
    var body: some View {
        NavigationView {
            VStack(spacing: 10) {
                
                Text("AppStorage를 업데이트하려면 변수에 새 값을 할당하면 된다.")
                    .font(.headline.bold())
                    .frame(height: 80)
                    .foregroundColor(.white)
                    .padding()
                    .multilineTextAlignment(.center)
                    .background(.red)
                    .padding(.bottom)
                
                HStack(spacing: 10) {
                    Text("새로운 닉네임 : ")
                    
                    TextField("닉네임변경", text: $newUsername)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                }
                .padding()
                
                Button {
                    /* 변수에 새 값을 할당해 AppStorage를 업데이트.
                     지금까지 @AppStorage키가 생성되지 않았다면, 여기서 값을 설정할 때 새로 생성된다.*/
                    username = newUsername
                } label: {
                    Text("업데이트")
                        .frame(height: 50)
                        .frame(maxWidth: .infinity)
                        .background(Color.gray)
                        .foregroundColor(.white)
                        .font(.headline.bold())
                        .cornerRadius(10)
                        .padding()
                }

            }
            .navigationTitle("AppStorage 업데이트")
        .navigationBarTitleDisplayMode(.large)
        }
    }
}
  • key를 생성하려면, username 변수에 값을 설정하면 된다.
  • @AppStorage에 대한 이 이니셜라이저는 "June"을 밸류로 설정하지 않음. 키인 ("username")이 없을 경우에 사용할 값임.

struct ContentView: View {
    @AppStorage("darkBackground") var darkBackground = false

    var body: some View {
        VStack {
            Text("@AppStorage")
                .font(.title)
            
            // @AppStorage 사용해 바인딩 가능. 데이터 저장할 필요 없음.
            Toggle(isOn: $darkBackground) {
                Text("다크모드 사용")
            }
            .font(.headline)
            .preferredColorScheme(darkBackground ? .dark : .light)
        }
        .padding()
    }
}

❗️주의

@AppStorage키에 false가 설정되어 있는게 아님!
키가 존재하지 않는 경우에만 사용됨!


구조체 저장하기

import SwiftUI

// Codable 프로토콜
struct User: Codable {
    var name = ""
    var age = 0
    
    // struct를 Data타입으로 인코딩함. 리턴값은 AppStorage에 실제로 저장되는 값.
    func encode() -> Data? {
        let encoder = JSONEncoder()
        
        if let encoded = try? encoder.encode(self) {
            return encoded
        } else {
            return nil
        }
    }
    
    // AppStorage에서 Data값을 가져오면, User 구조체로 다시 변환해 화면에 뿌려줄 수 있음.
    static func decode(userData: Data) -> User? {
        let decoder = JSONDecoder()
        
        if let user = try? decoder.decode(User.self, from: userData) {
            return user
        } else {
            return nil
        }
    }
}

struct StoringStruct: View {
    @AppStorage("user") var userData = User(name: "June", age: 365).encode()!
    @State private var userName = ""
    @State private var age = 0
    
    var body: some View {
        VStack {
            Text("구조체 저장하기")
                .font(.title)
            
            Text("이름: \(userName)").bold()
            Text("나이: \(age)").bold()
        }
        .onAppear {
            getAppStorageData()
        }
    }
    
    func getAppStorageData() {
        // Data타입이기 때문에 디코딩해야 함.
        if let appUser = User.decode(userData: userData) {
            userName = appUser.name
            age = appUser.age
        }
    }
}

struct StoringStruct_Previews: PreviewProvider {
    static var previews: some View {
        StoringStruct()
    }
}

Preview에서 @AppStorage 사용하기

struct AppStorage_Previews: PreviewProvider {

	// 꼭 static으로!
    @AppStorage("username") static var username: String!
    
    static var previews: some View {
        username = "미리보기에서 이름 세팅해놓음"
        
        return ContentView()
    }
}

프리뷰를 실행한다고 해서 해당 키로 AppStorage 값을 업데이트하는게 아님. 즉 편하게 마음껏 사용하면 됨.


AppStorage 이니셜라이저

아래 2가지 이니셜라이저는 똑같은 기능을 함

@AppStorage("BG") var BG = false 
  • 일반적으로 변수에 값을 할당할 때, 이와 같은 형식의 구문을 사용함.
  • 고로 @AppStorage 키가 생성되고, 이 값을 사용한다고 생각하기가 쉬움.

@AppStorage(wrappedValue: false, "BG") var BG 
  • 첫번째 구문과 역할은 같지만, 오해의 소지는 훨씬 줄음.
  • BG키가 앱 저장소에 없는 경우에 사용되는 기본값은 'wrappedValue', 즉 false임.
profile
안다고 착각하지 말기

0개의 댓글