Archive

[iOS] UserDefault Property Wrapper

lgvv 2022. 2. 24. 20:31

UserDefault Property Wrapper

 

(업데이트): 2022년 02월 24일: encode, decode 추가

 

아래 사이트에서 애플의 자세한 설명을 볼 수 있다.

 

https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md

 

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Lang

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhance...

github.com

 

 

✅ Property Wrapper에 대해서 알아보자

이전에도 Property Wrapper를 본적이 있었으나 SwiftUI를 공부하는데 @State, @Binding 등이 상당히 많이 등장하는 것임.

그래서 공부해야겠다고 느껴서 ㄱ ㄱ

 

✅ 예제코드

//
//  ViewController.swift
//  PropertyWrapper
//
//  Created by Hamlit Jason on 2022/02/24.
//

import UIKit

class ViewController: UIViewController {
    
    let userManager = UserManager()
    var number = NumberStruct()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("ViewDidLoad")
    }
    @IBAction func writeButton(_ sender: Any) {
        UserManager.userTouchID = "bb"
        print("UserManager.userTouchID \(UserManager.userTouchID)")
        number.value = 2200
    }
    @IBAction func readButton(_ sender: Any) {
        print("UserManager.userTouchID \(UserManager.userTouchID)")
        print("\(NumberStruct().value)")
        print("\(NumberStruct().$value)")
        
        print("\(number.value)")
        print("\(number.$value)")
        
    }
}

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T
    let storage: UserDefaults
    
    var wrappedValue: T {
        get { self.storage.object(forKey: self.key) as? T ?? self.defaultValue }
        set { self.storage.set(newValue, forKey: self.key) }
    }
    
    init(key: String, defaultValue: T, storage: UserDefaults = .standard) {
        self.key = key
        self.defaultValue = defaultValue
        self.storage = storage
    }
}

class UserManager {
    @UserDefault(key: Key.first.rawValue, defaultValue: nil, storage: .standard)
    static var userTouchID: String?
}

enum Key: String {
    case first = "firstTime"
}

@propertyWrapper
struct Max100orLess {
    private var number = 0
    private(set) var projectedValue: Bool
    
    var wrappedValue: Int {
        get { return number }
        set {
            if newValue > 100 {
                number = 100
                projectedValue = true
            } else {
                number = newValue
                projectedValue = false
            }
        }
    }
    
    init() {
        self.number = 0
        self.projectedValue = false
    }
}

struct NumberStruct {
    @Max100orLess var value: Int
}

코드 정리가 진짜 안되긴 했는데, 딱 보면 이해할 수 있음

 

🟠 결과

앱 처음 실행 후 - read Button - write Button - read Button 순으로 클릭

 

ViewDidLoad

// didTapReadButton
UserManager.userTouchID nil
0
false
0
false

// didTapWriteButton
UserManager.userTouchID Optional("bb")

// didTapReadButton
UserManager.userTouchID Optional("bb")
0
false
100
true

 

 

 

✅ (업데이트)2022년 02월 24일

 

우리는 구조체에서도 잘 먹히기를 바람.

 

 

UserDefaults는 Hashable는 Struct 등은 저장하기 어려우나

그냥 Data타입으로 Encoding하고 Decoding해서 사용한다면 어떤 타입이든 저장할 수 있음

@propertyWrapper
struct UserDefault<T: Codable> {
    let key: String
    let defaultValue: T
    let storage: UserDefaults

    var wrappedValue: T {
        get {
            guard let data = self.storage.object(forKey: self.key) as? Data else { return defaultValue }
            return (try? PropertyListDecoder().decode(T.self, from: data)) ?? self.defaultValue
        }
        set {
            let encodedData = try? PropertyListEncoder().encode(newValue)
            self.storage.set(encodedData, forKey: self.key)
        }
    }

    init(key: String, defaultValue: T, storage: UserDefaults = .standard) {
        self.key = key
        self.defaultValue = defaultValue
        self.storage = storage
    }
}

 

 

 

 

'Archive' 카테고리의 다른 글

[iOS] Swift 전처리문 #if DEBUG 사용하기  (0) 2022.02.19
[iOS] UTC to localTime 🗺  (0) 2022.02.19