-
Notifications
You must be signed in to change notification settings - Fork 0
学不动了.png(笑
@EFStorageUserDefaults(forKey: "它的 key")
var 某个存在_UserDefaults_里的值: String = "当不存在时使用的默认值"
let 用于读写的引用: EFStorageUserDefaultsRef<String> = UserDefaults.efStorage.某个_key
如果把上面那句完整地写出来的话,会是这样:
let 用于读写的引用 = EFStorageUserDefaultsRef<String>.forKey("某个_key")
这样就可以访问在 UserDefaults.standard
里那个 key 对应存储的内容了:
用于读写的引用.content
或者,如果你喜欢黑魔法的话,这样也可以:
UserDefaults.efStorage.某个_key as String?
如果可以推断类型的话,as String?
都可以不加。比如更改它的值就非常简单:
UserDefaults.efStorage.某个_key = "OwO"
所有的 @propertyWrapper 类型都有很多可以配置的参数,如果你不想存在默认容器里也没关系
@EFStorageUserDefaults(forKey: "某个标识符",
in: 另外的UserDefaults,
persistDefaultContent: true /*把默认值实际存储到容器里*/)
var 存在另外一个容器里的变量: Bool = 它的默认值
UserDefaults.另外的UserDefaults.efStorage.某个标识符 // 根据返回类型不同,可以是引用也可以是值
EFStorageUserDefaultsRef<Bool>.forKey("某个标识符", in: 另外的UserDefaults)
但是使用比如 App Group 的时候可能就需要全局替换了,不用担心,这个也能做到:
extension UserDefaults {
private static let appGroup = UserDefaults(
suiteName: kSecAttrAccessGroup as String
)
@_dynamicReplacement(for: makeDefault())
class func makeDefaultForAppGroup() -> Self {
return (UserDefaults.appGroup as? Self) ?? makeDefault()
}
}
我们之前一直用 UserDefaults 在举例子,但其实我们还可以组合一下,同时存到多个地方:
@EFStorageComposition( // <- 组合类型
EFStorageUserDefaults(wrappedValue: false, forKey: "isNewUser"),
EFStorageKeychainAccess(wrappedValue: false, forKey: "isNewUser"))
var 新用户: Bool
有的时候呢,我们可能还需要支持一下之前版本标识符的名称,这也是完全没问题的:
@SomeEFStorage( // 可以使用 + 来结合多个 EFStorage 哦
EFStorageKeychainAccess(wrappedValue: false, forKey: "paidBefore")
+ EFStorageUserDefaults(wrappedValue: false, forKey: "paidBefore")
+ EFStorageUserDefaults(wrappedValue: true, forKey: "oldHasPaidBeforeKey"))
var 给这个项目捐过款: Bool
但可能老版本里面存储的数据类型不一样,需要迁移呢?
@EFStorageComposition(
EFStorageUserDefaults<String>(wrappedValue: "Nah",
forKey: "理论上迁移的话key是一样的"),
EFStorageMigrate( // <-- 这就是你要找的
from: EFStorageUserDefaults<Int>( // <- 旧的容器
wrappedValue: 1551,
forKey: "但说实话key看情况一不一样无所谓",
persistDefaultContent: true),
by: { number in String(number) } // <- 迁移方式
)
)
var 我好了: String
虽然 EFStorage 已经扩展了常见类型以便您直接使用,但还是有时候 需要扩展其他(您自己的)类型才能存储到某个 EFStorage 中。 具体怎么做可以参考 EFStorage 的源代码,这里只做简单介绍。
public protocol KeychainAccessStorable {
func asKeychainAccessStorable() -> Result<AsIsKeychainAccessStorable, Error>
static func fromKeychain(_ keychain: Keychain, forKey key: String) -> Self?
}
KeychainAccess
只能放 String
和 Data
类型,所以您的类型必须转化成这两种中的一个:
public enum AsIsKeychainAccessStorable {
case string(String)
case data(Data)
}
public protocol UserDefaultsStorable {
func asUserDefaultsStorable() -> Result<AsIsUserDefaultsStorable, Error>
static func fromUserDefaults(_ userDefaults: UserDefaults, forKey key: String) -> Self?
}
UserDefaults
虽然可以放 Any
类型,但是不支持直接存储的类型被直接放进去的话会炸,
所以除非你想清楚了,建议不要继承 AsIsUserDefaultsStorable
这个协议,
因为理论上所有应该实现这个协议的类型已经实现了这个协议(没有的话请开 PR,谢谢)。
public protocol AsIsUserDefaultsStorable: UserDefaultsStorable { }
public protocol YYCacheStorable {
func asYYCacheStorable() -> Result<NSCoding, Error>
static func fromYYCache(_ yyCache: YYCache, forKey key: String) -> Self?
}
YYCache
因为是用 Objective-C 写的,所以只支持放 NSCoding
。
EFStorage 在要被存储的类型转换失败的时候会调用 assertionFailure
,也就是生产环境中不会炸,但也什么都不会做。
你可以通过 @_dynamicReplacement(for:)
来替换掉 onConversionFailure
/onStorageFailure
,
自己处理这些错误。