方式一
代码如下:
protocol UserDefaultNameSpace { }
extension UserDefaultNameSpace {
static func namespace<T>(_ key:T) -> String where T :RawRepresentable {
return "\(Self.self).\(key.rawValue) "
}
}
protocol UserDefaultSettable : UserDefaultNameSpace {
associatedtype UserDefaultKey : RawRepresentable
}
extension UserDefaultSettable where UserDefaultKey.RawValue == String {}
extension UserDefaultSettable {
/// 关于 Int 类型存储和读取
static func set(value:Int, forKey key:UserDefaultKey){
let key = namespace(key)
UserDefaults.standard.set(value, forKey: key)
}
static func integer(forKey key:UserDefaultKey) -> Int {
let key = namespace(key)
return UserDefaults.standard.integer(forKey: key)
}
/// 关于 String 类型存储和读取
static func set(value:Any?, forKey key:UserDefaultKey){
let key = namespace(key)
UserDefaults.standard.set(value, forKey: key)
}
static func string(forKey key:UserDefaultKey) -> String? {
let key = namespace(key)
return UserDefaults.standard.string(forKey: key)
}
}
extension UserDefaults {
/*! 关于账号的信息 Key 都放在这里 */
struct Account: UserDefaultSettable {
enum UserDefaultKey : String {
case name
case age
case birth
}
}
/*! 关于登陆情况 Key 都放在这里 */
struct LoginStatus: UserDefaultSettable {
enum UserDefaultKey:String {
case lastLoginTime
case sessionTime
}
}
}
/// 使用方式
UserDefaults.Account.set(value: 20, forKey: .age)
UserDefaults.Account.set(value: "pmst", forKey: .name)
UserDefaults.Account.set(value: "20170214", forKey: .birth)
方式二
卓同学的另一种实现思路:
public protocol UserDefaultSettable {
var uniqueKey: String { get }
}
public extension UserDefaultSettable where Self: RawRepresentable, Self.RawValue == String {
public func set(value: Any?){
UserDefaults.standard.set(value, forKey: uniqueKey)
}
public var value: Any? {
return UserDefaults.standard.value(forKey: uniqueKey)
}
public var stringValue: String? {
return value as? String
}
public func set(url: URL?) {
UserDefaults.standard.set(url, forKey: uniqueKey)
}
public var urlValue: URL? {
return UserDefaults.standard.url(forKey: uniqueKey)
}
public var uniqueKey: String {
return "\(Self.self).\(rawValue)"
}
/// removed object from standard userdefaults
public func removed() {
UserDefaults.standard.removeObject(forKey: uniqueKey)
}
}
extension UserDefaults {
enum TestData: String,UserDefaultSettable {
case name
case url
}
}
let value = "testValue"
if let _ = UserDefaults.TestData.name.stringValue {
assertionFailure("should be nil")
}
UserDefaults.TestData.name.set(value: value)
UserDefaults.TestData.name.stringValue
当然这里我们还商讨了下命名规则,觉得set
,stringValue
不是很恰到,之后会改成 store 动词。
方式三:
智多芯的博客中又提到了一种方式,我觉得也比较好,贴下代码:
final class PreferenceKey<T>: PreferenceKeys { }
class PreferenceKeys: RawRepresentable, Hashable {
let rawValue: String
required init!(rawValue: String) {
self.rawValue = rawValue
}
convenience init(_ key: String) {
self.init(rawValue: key)
}
var hashValue: Int {
return rawValue.hashValue
}
}
extension PreferenceKeys {
static let launchAtLogin = PreferenceKey<Bool>("LaunchAtLogin")
static let launchCount = PreferenceKey<Int>("LaunchCount")
static let userInfo = PreferenceKey<UserInfo>("UserInfo")
}
接着定义一个专门负责存储的管理类
final class PreferenceManager {
static let shared = PreferenceManager()
let defaults = UserDefaults.standard
private init() {
registerDefaultPreferences()
}
private func registerDefaultPreferences() {
// Convert dictionary of type [PreferenceKey: Any] to [String: Any].
let defaultValues: [String: Any] = defaultPreferences.reduce([:]) {
var dictionary = $0
dictionary[$1.key.rawValue] = $1.value
return dictionary
}
defaults.register(defaults: defaultValues)
}
}
let defaultPreferences: [PreferenceKeys: Any] = [
.launchAtLogin: false,
.launchCount: 0,
.userInfo: NSKeyedArchiver.archivedData(withRootObject: UserInfo(id: 0, name: "")),
]
extension 补充下:
extension PreferenceManager {
subscript(key: PreferenceKey<Any>) -> Any? {
get { return defaults.object(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<URL>) -> URL? {
get { return defaults.url(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<[Any]>) -> [Any]? {
get { return defaults.array(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<[String: Any]>) -> [String: Any]? {
get { return defaults.dictionary(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<String>) -> String? {
get { return defaults.string(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<[String]>) -> [String]? {
get { return defaults.stringArray(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<Data>) -> Data? {
get { return defaults.data(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<Bool>) -> Bool {
get { return defaults.bool(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<Int>) -> Int {
get { return defaults.integer(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<Float>) -> Float {
get { return defaults.float(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<Double>) -> Double {
get { return defaults.double(forKey: key.rawValue) }
set { defaults.set(newValue, forKey: key.rawValue) }
}
subscript(key: PreferenceKey<UserInfo>) -> UserInfo? {
get {
var object: UserInfo?
if let data = defaults.data(forKey: key.rawValue) {
object = NSKeyedUnarchiver.unarchiveObject(with: data) as? UserInfo
}
return object
}
set {
if let object = newValue {
let data = NSKeyedArchiver.archivedData(withRootObject: object)
defaults.set(data, forKey: key.rawValue)
}
}
}
}
使用方式如下:
let Preferences = PreferenceManager.shared
func demo() {
let userDefaults = UserDefaults.standard
// Test data.
var launchAtLogin = true
var launchCount = 10
var userInfo: UserInfo? = UserInfo(id: 123, name: "Fox")
// Write preference.
Preferences[.launchAtLogin] = launchAtLogin
Preferences[.launchCount] = launchCount
Preferences[.userInfo] = userInfo
// Read preference.
launchAtLogin = Preferences[.launchAtLogin]
launchCount = Preferences[.launchCount]
userInfo = Preferences[.userInfo]
// Check preferences.
for (key, value) in userDefaults.dictionaryRepresentation() {
print("\(key): \(value)")
}
}