본문 바로가기

학습 노트/Swift UI (2022)

33. AppStorage & SceneStorage

AppStorage & SceneStorage


AppStorarage와 SceneSotrage는 사용자의 선택사항을 저장한다.
둘을 사용하지 않고도 CoreData, Text file, Binary File을 사용해 구현하는 것도 가능하지만,
초기화 코드가 필요하고, 이를 위한 코드의 양이 만만치 않다.

따라서 SwiftUI에서는 OS가 제공하는 Default System이라는 기본 형식을 저장하는 기본 DB를 사용해 이를 간단히 해결할 수 있다.
이는 userDefaults로 Dictionary와 비슷하게 기능한다.

AppStorage와 SceneStorage는 비슷하게 기능하지만.
이름대로 각각 App 전체와 특정 Scene에서 유효하다는 차이가 존재한다.

@State private var number = 0
@State private var color = Color.yellow

Scene에는 두 개의 버튼이 존재하고, 각각 State 변수인 number, color를 무작위로 변경한다.

이렇게 일반적으로 View의 상태를 표시하기 위한 State 변수는 Scene을 나갔다 들어오면 초기화되는
휘발성을 가지는 한계가 존재한다.

@SceneStorage("number") private var number = 0
@State private var color = Color.yellow
@AppStorage("number") private var number = 0
@State private var color = Color.yellow

 

이중 number를 SceneStorage로 선언하게 되면
Scene을 벗어났음에도 number는 유지되고, color는 초기화되는 것을 확인할 수 있다.

마찬가지로 AppStorage로 선언하면 앱을 종료해도 number 데이터를 유지한다.

RawRepresentable

 

Apple Developer Documentation

 

developer.apple.com

문제는 AppStorage와 SceneStorage가 모든 데이터를 지원하지는 않는다는 점이다.
기본적으로 integer, double, string 등의 기본 자료형만 지원하기 때문에,
Color를 저장하는 color 변수는 이들을 사용할 수 없다.
이러한 경우 RawRepresentable을 사용한다.

extension Color: RawRepresentable {
    public init?(rawValue: RawValue) {

    }

    public var rawValue: RawValue {

    }
}

사용항 Type에 RawRepresentable 프로토콜을 채용하고,
rawValue를 파라미터로 가지는 생성자와 rawValue 변수를 하나 선언한다.

extension Color: RawRepresentable {
    public init?(rawValue: String) {
        guard let data = Data(base64Encoded: rawValue) else {
            self = .black
            return
        }
    }

    public var rawValue: RawValue {

    }
}

생성자에 전달된 rawValue가 base64 디코딩이 가능한 경우 다음 동작을 실행하고,
그렇지 않은 경우 '.black'으로 설정한다.

extension Color: RawRepresentable {
    public init?(rawValue: String) {
        guard let data = Data(base64Encoded: rawValue) else {
            self = .black
            return
        }

        do {
            let color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor ?? .black
            self = Color(color)
        } catch {
            self = .black
        }
    }

    public var rawValue: String {

    }
}

data를 UIColor 형식으로 변환하고, 이것을 저장한다.
불가능한 경우 '.black'으로 저장한다.

extension Color: RawRepresentable {
    public init?(rawValue: String) {
        guard let data = Data(base64Encoded: rawValue) else {
            self = .black
            return
        }

        do {
            let color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor ?? .black
            self = Color(color)
        } catch {
            self = .black
        }
    }

    public var rawValue: String {
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: UIColor(self), requiringSecureCoding: false) as Data
            return data.base64EncodedString()
        } catch {
            return ""
        }
    }
}

변수는 data를 다시 인코딩해 반환한다.

@AppStorage("number") private var number = 0
@SceneStorage("color") private var color = Color.yellow

이제는 Color 형식의 변수도 SceneStorage나 AppStorage를 적용할 수 있다.

'학습 노트 > Swift UI (2022)' 카테고리의 다른 글

32. CoreData #2  (0) 2022.11.17
31. CoreData #1  (0) 2022.11.16
30. Gesture  (0) 2022.11.16
29. List의 부가 기능 구현하기  (0) 2022.11.10
28. ForEach & Grid  (0) 2022.11.09