반응형
LinkedIn 개발자로 성장하면서 남긴 발자취들을 확인하실 수 있습니다.
Github WWDC Student Challenge 및 Cherish, Tiramisul 등 개발한 앱들의 코드를 확인하실 수 있습니다.
개인 앱 : Cherish 내 마음을 들여다보는 시간, 체리시는 디자이너와 PM과 함께 진행 중인 1인 개발 프로젝트입니다.
10년 후, 20년 후 나는 어떤 스토리 텔러가 되어 있을지 궁금하다. 내가 만약에 아직 조금 더 탐구하고 싶은 게 있고, 궁금한 게 있다면, 그게 설사 지금 당장의 내 인생에 도움이 안 되는 것 같더라도 경험해보자. 그 경험들을 온전히 즐기며 내 것으로 만들고, 내 일에 녹여내고... 그러다보면 그 점들이 모여 나란 사람을 그려내는 선이 될 테니까.

Recent Posts
Recent Comments
Total
관리 메뉴

꿈꾸는리버리

AppStorage 본문

오뚝이 개발자/SwiftUI

AppStorage

rriver2 2022. 4. 29. 01:04
반응형

 UserDefault  vs  AppStorage 

: UIKit 에서 userDefault를 사용했더라면, swiftUi에서는 appStorage를 사용한다! (appStorage는 property wrappers)

 

새로 추가된 거라면 무언가가 좋아졌다는 의미겠쥬..?

UIkit에서 유저디폴트를 저장하고 업데이트 하는 개발자가 코드로 짰어야 했다면 (명령형)

swiftUI에서는 그냥 appStorage 쓰면 알아서 해준다는 것 ! (선언형)

 

UIKit 공부하신 분이 아니고 appStorage가 처음이라면

굳이 userDefault 사용법과 swiftUI 사용법을 비교하지는 않아도 ... 되지 않을까..

우선 , appStorage가 무엇인지, 그리고 어떻게 써야 하는지를 알아야 한다고 생각합니다..

그리고 본 포스팅은 appStorage이 무엇인지와 어떻게 써야 하는지에 대해 다루고 있다.


 appStorage가 뭘까 ? 

하단 gif와 같이 @State를 사용하면,

import SwiftUI

struct SwiftUIView: View {
    @State var username = "River"
    
    var body: some View {
        VStack{
            Text("username : \(username)")
            
            Button(action: {
                username = "River2"
            }){
                Text("change userName")
            }
        }
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
    }
}

 

username을 "River"에서 "River2"로 값을 바꿔도 앱을 껐다 키게 되었을 때

username은 처음 "River"로 초기화가 된다.

 

만약 사용자가 껐다 켜도 해당 내용을 저장하고 싶을 때 사용하는 것이 appStorage이다.

다시 말해서 @AppStorage을 사용하면 앱을 껐다 켜도 해당 내용이 저장되어 있다.

하지만 너무 많은 데이터는 서버를 두고 서버랑 통신하면서 써야한다.

너무 당연한 말이지만, 유저 폰에 많은 양의 데이터를저장하면.. 앱이 너무 heavy해 진다.

또한, @AppStorage을 사용하면 @State처럼 View을 바인딩해서 사용할 수 있다.

 


 appStorage 사용법 

@AppStorage(키값) var (변수명) = (키값이 존재하지 않을 때 들어갈 기본 값)

 

AppStorage에 key : value 느낌으로 값이 저장되어 있고 

우리는 key 값으로 value를 찾아가지고 그 value 값을 변수에 넣고 사용하게 되는 거다.

 

@AppStorage("name1") var userName1 : String = "River"

-> key 값이 "name1"인 value를 찾아가지고 그 value 값을 userName1 변수에 넣고 사용한다.

 

 

 

히히 이제 이렇게 하면 앱을 껐다 지워도 River2로 바껴져 있는 것을 확인할 수 있다 !

import SwiftUI

struct AppStorageView: View {
    @AppStorage("name1") var userName1  = "River"
    
    var body: some View {
        VStack{
            Text("AppStorageView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName1)")
            
            Button(action: {
                if(userName1 == "River"){
                    userName1 = "River2"
                }else{
                    userName1 = "River"
                }
            }){
                Text("change userName")
            }

        }
    }
}

 

참 쉽죠 ???

근데 그 뒤에 사악한 얼굴이... (두근)


 appStorage.. 주의해야 하는 사항들 

아래 코드를 보고 "AppStorageSubView2 나타나랏 !" 버튼을 눌렀을 때 어떤 뷰가 그려질지 상상해보자,...

 

 

부모 뷰인 AppStorageView에 

  @AppStorage("name3") var userName3  = "River" 를 ,

 

자식 뷰인 AppStorageSubView2에 

 @AppStorage("name3") var userName3 : String 를 넣은 것에 집중해서 코드를 읽어보장

 

import SwiftUI

struct AppStorageView: View {
    @AppStorage("name3") var userName3  = "River"
    
    @State var isShowAppStorageSubView2 = false
    
    var body: some View {
        VStack{
            Text("AppStorageView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
            Button(action: {
                isShowAppStorageSubView2 = true
            }){
                Text("AppStorageSubView2 나타나랏 !")
            }

            if(isShowAppStorageSubView2 == true){
                AppStorageSubView2()
            }
        }
    }
}

struct AppStorageSubView2: View {
    @AppStorage("name3") var userName3 : String 
    
    var body: some View {
        VStack{
            Text("SubView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
        }.padding()
    }
}

 

ㅎ... 나만 이렇게 꿈꿨나..? 

 

근데 현실은 !! 에러 발생 

우헤헤 왜 에러가 뜨지?

 

바인딩이니까 AppStorageSubView2에 

@AppStorage("name3") var userName3 : String  = "어떤 이름"

이렇게 "어떤 이름"을 적는게 아니지 않나...???

 

 1) 선언에서의 오해  

우리가 기존에 밑과 같은 식을 적으면 userName3에 River가 들어가게 된다. 

var userName3  = "River"

 

하지만 @AppStorage에서는 key가 "name3"인 value에 "River"을 넣고, 이 값을 userName3에 쓰겠어! 라는 의미가 아니다.

    @AppStorage("name3") var userName3  = "River"

진짜 의미

 ->"name3"인 key가 있으면 해당하는 value을 userName3에 넣고,

만약에 "name3" key가 없으면 임시로 userName3에 "River"를 넣겠다는 의미를 가진다.

 

근데 알고 봐도 헷갈리잖아요...

그래서 혼란스럽지 않도록 밑에 식처럼 적는 것을 추천한다. (위 code와 같은 의미)

위에가 좀 더 쉽게 작성할 수 있지만,, 가독성이 떨어지더라도 아래처럼 적는 게 헷갈리지 않는다..!

@AppStorage(wrappedValue: "River", "name3") var userName3

 

 2) 선언에서의 오해2 

위에서 에러가 났던 코드를 고쳐보자.

 

일단 급한대로 서브뷰인 AppStorageSubView2에

@AppStorage("name3") var userName3 : String  = ""

라고 =""을 추가해보았다.

 

자, 이제 어떤 일이 벌어질까..? (두근)

import SwiftUI

struct AppStorageView: View {
    @AppStorage("name3") var userName3  = "River"
    
    @State var isShowAppStorageSubView2 = false
    
    var body: some View {
        VStack{
            Text("AppStorageView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
            Button(action: {
                isShowAppStorageSubView2 = true
            }){
                Text("AppStorageSubView2 나타나랏 !")
            }

            if(isShowAppStorageSubView2 == true){
                AppStorageSubView2()
            }
        }
    }
}

struct AppStorageSubView2: View {
    @AppStorage("name3") var userName3 : String = ""
    
    var body: some View {
        VStack{
            Text("SubView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
        }.padding()
    }
}

 

예상대로는 됐는데,,

사실 내가 원하는 게 이건 아니잖아?

 

부모뷰인 AppStorageView에서의 userName3 값인 "River"를 SubView에 가져오고 싶은데 ...

그리고 서브뷰인 AppStorageSubView2에서 넣었던 "" 값이 그대로 뜨네??

 

 

앞서 말했던 정의 부분을 다시 봐 보자..

    @AppStorage("name3") var userName3  = "River"

 ->"name3"인 key가 있으면 해당하는 value을 userName3에 넣고,

만약에 "name3" key가 없으면 임시로 userName3에 "River"를 넣겠다는 의미를 가진다.

 

==> Bold 체의 말을 다시 말하면 userName3에는 "River"값이 들어가지만, 

key가 "name3"인 곳에는 "River" 값이 들어가지 않았다는 것이다.

다시 말해서 key가 "name3"인 값은 아직도 존재하지 않다는 것이다!!! ㅎㅎ...

 

 

ㅎ... 그럼 어케 만들죠..?

AppStorageView에 "make userName" 버튼으로 key가 "name3"인 곳에는 "River22"를 value로 넣어주었다.

import SwiftUI

struct AppStorageView: View {
    @AppStorage("name3") var userName3  = "River"
    @AppStorage(wrappedValue: "River", "name4") var userName4
    
    @State var isShowAppStorageSubView2 = false
    
    var body: some View {
        VStack{
            Text("AppStorageView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
            
           	Button(action: {
                userName3 = "River22"
            }){
                Text("make userName")
            }
            .padding()
            .foregroundColor(Color.red)
            .padding()
            .foregroundColor(Color.red)
            
            Button(action: {
                isShowAppStorageSubView2 = true
            }){
                Text("AppStorageSubView2 나타나랏 !")
            }

            if(isShowAppStorageSubView2 == true){
                AppStorageSubView2()
            }
        }
    }
}

struct AppStorageSubView2: View {
    @AppStorage("name3") var userName3 : String = ""
    
    var body: some View {
        VStack{
            Text("SubView")
                .font(.system(size: 40))
            Text("appStorage1 : \(userName3)")
        }.padding()
    }
}

struct AppStorageView_Previews: PreviewProvider {
    @AppStorage("username1") static var userName1 : String!
    @AppStorage("username2") static var userName2 : String!
    
    static var previews: some View {
        AppStorageView()
    }
}

 

 

이제 이러구 나묘눈..

 

짜란 ~~ 

부모 뷰인 AppStorageView와 자식 뷰인 AppStorageSubView2 모두 "River22"가 보이는 것을 알 수 있다.

 

버튼을 눌렸을 때 key가 "name3"인 곳에 value로 "River22"가 들어갔고,

이제 @AppStorage에 key가 name3인 값이 존재하기 때문에

더 이상  @AppStorage에 key 값이 없을 때 userName에 넣어줬던 "River" 값과 ""이 안 들어가고, 

"name3" key에 해당하는 값인 "River22"가 들어간다.

 

 정리 

 1) AppStorage 언제 사용 ?

  1. 앱을 껐다 켜도 해당 내용이 저장하고 싶을 때
  2. @State처럼 View 바인딩해서 사용하고 싶을 때
  3. 작은 양의 데이터를 저장하고 싶을 때

2) AppStorage 사용법 

@AppStorage("name3") var userName3 = "River"
// 위 아래 둘 다 같은 code
@AppStorage(wrappedValue: "River", "name3") var userName3

: name3는 key값, userName3은 변수 값, River는 key가 존재하지 않을 시에 들어갈 값

 

3) 선언할 때의 혼란 블랙홀에 빠지지 않기

반응형

'오뚝이 개발자 > SwiftUI' 카테고리의 다른 글

SwiftUI : Custom Color  (0) 2022.05.24
SwiftUI : dark mode preview  (0) 2022.05.24
onAppear vs onRecieve  (0) 2022.05.01
@EnvironmentObject ????  (0) 2022.05.01
@StateObject vs @ObservedObject  (2) 2022.04.28
Comments