iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0
Mobile Development

在 iOS 開發路上的大小事2系列 第 4

【在 iOS 開發路上的大小事2-Day04】App 內的簡易儲存方式,UserDefaults

  • 分享至 

  • xImage
  •  

在 iOS App 裡,Apple 提供了兩種原生持久化儲存資料的方式
一種是今天要講的 UserDefaults、一種是 CoreData
CoreData 是屬於資料庫方面的資料儲存解決方案,不是今天的主角,所以就先不討論

UserDefaults 是一種 Key-Value 的簡易、持久性儲存資料的方式
提供了 String、Array、Dictionary、Data、String Array、Int、Float、Double、Bool、URL 等儲存格式

// 取自 Xcode 內的 Foundation/NSUserDefaults/UserDefaults

open func string(forKey defaultName: String) -> String?

open func array(forKey defaultName: String) -> [Any]?

open func dictionary(forKey defaultName: String) -> [String : Any]?

open func data(forKey defaultName: String) -> Data?

open func stringArray(forKey defaultName: String) -> [String]?

open func integer(forKey defaultName: String) -> Int

open func float(forKey defaultName: String) -> Float

open func double(forKey defaultName: String) -> Double

open func bool(forKey defaultName: String) -> Bool

@available(iOS 4.0, *)
open func url(forKey defaultName: String) -> URL?

所以就來將 UserDefaults 寫成一個 class 來管理吧

class UserPreference {
    static let shared = UserPreference()
    private let userPreference: UserDefaults
    private init() {
        userPreference = UserDefaults.standard
    }
}

UserDefaults 的給值、讀值方式如下~

// 給值
// 你要給這個值的 Key,要用 String 來表示
userPreference.set(你要給的值, forKey: 你要給這個值的 Key)

// 讀值
// 根據你要給的值的型態來決定
// Int
userPreference.integer(forKey: 你要讀的那個值的 Key)

// String
userPreference.string(forKey: 你要讀的那個值的 Key)

// Float
userPreference.float(forKey: 你要讀的那個值的 Key)

// Double
userPreference.double(forKey: 你要讀的那個值的 Key)

// Data
userPreference.data(forKey: 你要讀的那個值的 Key)

// String Array
userPreference.stringArray(forKey: 你要讀的那個值的 Key)

// Bool
userPreference.bool(forKey: 你要讀的那個值的 Key)

// Dictionary
userPreference.dictionary(forKey: 你要讀的那個值的 Key)

// Array
userPreference.array(forKey: 你要讀的那個值的 Key)

// URL
userPreference.url(forKey: 你要讀的那個值的 Key)

然後 Key 的部分,我們可以寫一個 enum 來管理,像是下面這樣

enum UserPreference: String {
    case email // 使用者的 Email
    case username // 使用者的名字
    case age // 使用者的年齡
    case height // 使用者的身高
    case weight // 使用者的體重
    case isActivate // 使用者的帳號啟用狀態
}

然後在讀值、給值方面,可以像下面這樣寫,透過 get/set 的方式來完成

var email: String {
    get { return userPreference.string(forKey: UserPreference.email.rawValue) ?? "" }
    set { return userPreference.set(newValue, forKey: UserPreference.email.rawValue) }
}
var username: String {
    get { return userPreference.string(forKey: UserPreference.username.rawValue) ?? "" }
    set { return userPreference.set(newValue, forKey: UserPreference.username.rawValue) }
}
var age: Int {
    get { return userPreference.integer(forKey: UserPreference.age.rawValue) }
    set { return userPreference.set(newValue, forKey: UserPreference.age.rawValue) }
}
var height: Double {
    get { return userPreference.double(forKey: UserPreference.height.rawValue) }
    set { return userPreference.set(newValue, forKey: UserPreference.height.rawValue) }
}
var weight: Double {
    get { return userPreference.double(forKey: UserPreference.weight.rawValue) }
    set { return userPreference.set(newValue, forKey: UserPreference.weight.rawValue) }
}
var isActivate: Bool {
    get { return userPreference.bool(forKey: UserPreference.isActivate.rawValue) }
    set { return userPreference.set(newValue, forKey: UserPreference.isActivate.rawValue) }
}

所以整個 class 就會長得像是下面這樣~

class UserPreference {
    static let shared = UserPreference()
    private let userPreference: UserDefaults
    private init() {
        userPreference = UserDefaults.standard
    }
    
    enum UserPreference: String {
        case email // 使用者的 Email
        case username // 使用者的名字
        case age // 使用者的年齡
        case height // 使用者的身高
        case weight // 使用者的體重
        case isActivate // 使用者的帳號啟用狀態
    }
    
    var email: String {
        get { return userPreference.string(forKey: UserPreference.email.rawValue) ?? "" }
        set { return userPreference.set(newValue, forKey: UserPreference.email.rawValue) }
    }
    var username: String {
        get { return userPreference.string(forKey: UserPreference.username.rawValue) ?? "" }
        set { return userPreference.set(newValue, forKey: UserPreference.username.rawValue) }
    }
    var age: Int {
        get { return userPreference.integer(forKey: UserPreference.age.rawValue) }
        set { return userPreference.set(newValue, forKey: UserPreference.age.rawValue) }
    }
    var height: Double {
        get { return userPreference.double(forKey: UserPreference.height.rawValue) }
        set { return userPreference.set(newValue, forKey: UserPreference.height.rawValue) }
    }
    var weight: Double {
        get { return userPreference.double(forKey: UserPreference.weight.rawValue) }
        set { return userPreference.set(newValue, forKey: UserPreference.weight.rawValue) }
    }
    var isActivate: Bool {
        get { return userPreference.bool(forKey: UserPreference.isActivate.rawValue) }
        set { return userPreference.set(newValue, forKey: UserPreference.isActivate.rawValue) }
    }
}

在其他檔案呼叫的時候就可以像下面這樣來呼叫~

var email: String = UserPreference.shared.email
var username: String = UserPreference.shared.username
var age: Int = UserPreference.shared.age
var height: Double = UserPreference.shared.height
var weight: Double = UserPreference.shared.weight
var isActivate: Bool = UserPreference.shared.isActivate

這樣 Code 看起來就會清晰很多了~

這樣也同時解決去年實作 Firebase Auth 登入,重開 App 沒辦法紀錄登入狀態的問題~

參考資料

  1. https://developer.apple.com/documentation/foundation/userdefaults
  2. https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/741066/#outline__1_1
  3. https://www.jianshu.com/p/3796886b4953

上一篇
【在 iOS 開發路上的大小事2-Day03】工人智慧!JSON 轉起來
下一篇
【在 iOS 開發路上的大小事2-Day05】更新到 iOS 15 後踩過的坑
系列文
在 iOS 開發路上的大小事230
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言