-
Notifications
You must be signed in to change notification settings - Fork 0
ApolloZhu edited this page Sep 18, 2019
·
4 revisions
最后,我们再来看看如何把你的存储方案也适配 EFStorage。
// 如果是用 Swift Package Manager 集成的话:
import EFStorageCore
// CocoaPods 集成的则还是一样导入:
import EFStorage
接下来我们就可以开始了。
注意:把实例中的
<#ExampleStorage#>
替换为实际你存储方案的名字!
extension <#ExampleStorage#>: EFUnderlyingStorage {
public class func makeDefault() -> Self {
// ... 这个方法返回默认容器的实现
}
}
有的时候,你的存储方案并不一定能够成功构造一个默认容器,这种情况则实现 EFFailableUnderlyingStorage
:
extension <#ExampleStorage#>: EFFailableUnderlyingStorage {
public class func makeDefault() -> Self? {
// ... 返回默认容器或者 nil
}
}
public protocol <#ExampleStorage#>Storable {
func as<#ExampleStorage#>Storable() -> <#ExampleStorage#>Storable//可以看情况加上 ! 或者 ?
static func from<#ExampleStorage#>(_ <#exampleStorage#>: <#ExampleStorage#>, forKey key: String) -> Self?
}
然后(通过添加 extension 等方法)让需要被存储的(常见)类型实现 <#ExampleStorage#>Storable
协议。
当然,这个协议完全是由你决定的,所以像自带的几个存储方案返回
Result<StorableType, Error>
, 甚至写成和上面的协议完全不一样也是可以的。
继承 EFStorage 的优良传统/原始设计,我们通过实现 EFSingleInstanceStorageReference
来“保证”这是个单例
public class EFStorage<#ExampleStorage#>Ref<Content: <#ExampleStorage#>Storable>: EFSingleInstanceStorageReference {
public required init(
// 这个看起来很长的参数是说,不要直接调用这个构造器,否则后果自负
iKnowIShouldNotCallThisDirectlyAndIsResponsibleForUnexpectedBehaviorMyself: Bool,
forKey key: String, in storage: <#ExampleStorage#>//? // 根据情况加上
) {
self.key = key
self.storage = storage
self.content = Content.from<#ExampleStorage#>(storage, forKey: key)
}
public let key: String
public let storage: <#ExampleStorage#>//?
public var content: Content? {
didSet {
if let newValue = content {
storage/*?*/.set(newValue.as<#ExampleStorage#>Storable(), forKey: key)
} else {
storage/*?*/.removeObject(forKey: key)
}
}
}
}
你可以不这么做,但我想不明白为什么。
@propertyWrapper
public struct EFStorage<#ExampleStorage#><Content: <#ExampleStorage#>Storable>: EFSingleInstanceStorageReferenceWrapper {
public var _ref: EFStorage<#ExampleStorage#>Ref<Content>
public var wrappedValue: Content {
get {
if let content = _ref.content { return content }
let defaultContent = makeDefaultContent()
if persistDefaultContent { _ref.content = defaultContent }
return defaultContent
}
set { _ref.content = newValue }
}
public let persistDefaultContent: Bool
public let makeDefaultContent: () -> Content
public func removeContentFromUnderlyingStorage() {
_ref.content = nil
}
public init(
__ref: EFStorage<#ExampleStorage#>Ref<Content>,
makeDefaultContent: @escaping () -> Content,
persistDefaultContent: Bool
) {
self._ref = __ref
self.makeDefaultContent = makeDefaultContent
self.persistDefaultContent = persistDefaultContent
}
}
谁不喜欢黑魔法呢?
public extension EFUnderlyingStorageWrapper {
subscript<T: <#ExampleStorage#>Storable>(
dynamicMember key: String
) -> T? where Base == <#ExampleStorage#> {
get {
return EFStorage<#ExampleStorage#>Ref.forKey(key, in: base).content
}
set {
EFStorage<#ExampleStorage#>Ref.forKey(key, in: base).content = newValue
}
}
subscript<T: <#ExampleStorage#>Storable>(
dynamicMember key: String
) -> T? where Base == <#ExampleStorage#>.Type {
get {
return EFStorage<#ExampleStorage#>Ref.forKey(key).content
}
set {
EFStorage<#ExampleStorage#>Ref.forKey(key).content = newValue
}
}
}