UserDefault Property Wrapper
(업데이트): 2022년 02월 24일: encode, decode 추가
✅ 아래 사이트에서 애플의 자세한 설명을 볼 수 있다.
https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md
✅ 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 |