본문 바로가기

iOS 프로그래밍

UserDefaults에 custom object 저장하기

이번에 iOS 14가 나오면서 저희 회사 어플도 위젯을 만들어 보고 싶어

제가 제안하여 만들었었는데요

 

만들다 보니 아직 위젯이 단순 뷰어의 형태를 가지고 있어

위젯에서 직접 API에서 데이터를 받아와 뷰에 보여는 것이나

timeLine에 따라 계속 데이터를 받아오는 형태로 진행했던 것이 불필요 하다고 느꼈습니다.

 

 

그래서 어차피 어플에서 사용하는 데이터를 보여 주는 것이기 때문에 

어플에서 데이터가 세팅되면 UserDefault에 적용 하는 형태로 

API 에서 받아온 데이터를 어플에서 직접 형태에 맞게 변경 후 struct(구조체) 자체를 저장하고 싶었습니다.

 

하지만 UserDefault는 key:value 값으로

이 value 값이 Any여도 저희가 만든 custom object를 알진 못하겠죠??ㅎㅎ

 

이렇게 저장하고 싶다면

구조체 -> Json -> Data -> UserDefault

구조체 -> Json -> Data -> UserDefault

와 같은 형태로 변형하는 과정이 있어야 하고

 

꺼내 올 때도

UserDefault -> Data -> Json -> 구조체

UserDefault -> Data -> Json -> 구조체

이러한 형식으로 진행되어야 합니다.

 

아마 구조체를 바로 저장하려 한다면

Attempt to insert non-property list object ~(구조체 형태)

이런 오류가 날것입니다


해결 방법 1.

medium.com/flawless-app-stories/save-custom-objects-into-userdefaults-using-codable-in-swift-5-1-protocol-oriented-approach-ae36175180d8

 

위와 같은 블로그를 참고하여 

extension을 만들어 적용하는 방식이 있습니다.

codable을 사용하고 있고 extension을 만들어 놓는다면 수정 시

가지고 있는 지식이 딱히 없어도 만들 수 있다는 장점이 있지만

extension 파일 하나가 더 만들어져야 하고

저에게는 do catch 문이 들어가야하는 것이 코드가 길어져 맘에 들지 않아 다른 방법으로 해보았습니다.

 

해결 방법 2.

@propertyWrapper로 UserDefault get set 기능이 있는 UserDefaultWrapper 란 구조체를 만듭니다.

 

@UserDefaultWrapper(key: "progressData") private var progressData: Data? 그 후 이러한 변수를 만들고

let encode = JSONEncoder()
let data = try? encode.encode(구조체명)
progressData = data

 

get 할 때 반대 순서로 decode 하면 되겠죠?

 

-> property Wrapper 에 대한 이해가 없으시다면

jcsoohwancho.github.io/2019-10-21-Property-Wrapper%EB%9E%80/