Foreword
Before this paper we define a Parsable
for deserialization
protocol Parsable {
static func parse(data: Data) -> Result<Self>
}
复制代码
If we give the type of custom add a persistent feature, the same can also define a protocol that type comply with this agreement have 持久化
this feature.
Cachable
public protocol Cachable {
/// 存入沙盒
///
/// - Parameter path: 路径
/// - Returns: 结果
@discardableResult
func save(at path: String) -> Result<Void, Error>
/// 从沙盒中取
///
/// - Parameter path: 路径
/// - Returns: 结果
static func get(fromCache path: String) -> Self?
}
复制代码
Cachable
It defines two methods deposit and take, then we have to Cachable
add the default implementation.
Codable
Most of the serialization and de-serialization will use very convenient inCodable
extension Cachable where Self: Codable {
@discardableResult
public func save(at path: String) -> Result<Void, Error> {
let url = URL(fileURLWithPath: path)
do {
let data = try JSONEncoder().encode(self)
try data.write(to: url)
return .success(())
} catch {
print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
return .failure(error)
}
}
public static func get(fromCache path: String) -> Self? {
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
return try JSONDecoder().decode(self, from: data)
} catch {
print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
return nil
}
}
}
复制代码
As a result, the type of follow up Codable
and also want to follow Cachable
you free access to the above two methods.
struct Car: Codable {
var engine: String
var name: String
var type: String
}
extenstion Car: Cachale {}
// 获取沙盒中缓存的car
let carCachePath = getMyCarCachePath()
let myCacheCar = Car.get(fromCache: carCachePath)
// 缓存bmw
let bmw = Car(engine: "V8", name: "X7", type: "xDrive50i")
bmw.save(at: carCachePath)
复制代码
Note: We use @discardableResult
marked save(at:)
method, the purpose is to let the compiler does not warn us not to use save(at:)
the return value. Many ways chained calls to have this mark, for example Alamofire
on the use of the mark.
String、Data
We can also give String
and Data
also add this functionality.
extension Cachable where Self == String {
@discardableResult
public func save(at path: String) -> Result<Void, Error> {
let url = URL(fileURLWithPath: path)
do {
if let data = self.data(using: .utf8) {
try data.write(to: url)
return .success(())
} else {
return .failure(WWError.stringToDataError)
}
} catch {
print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
return .failure(error)
}
}
public static func get(fromCache path: String) -> Self? {
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
return self.init(data: data, encoding: .utf8)
} catch {
print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
return nil
}
}
}
复制代码
Data
The same is true, we may have to go to achieve.
SwiftProtobuf
If you have to use SwiftProtobuf
it can also give SwiftProtobuf
the Message
add this functionality.
extension Cachable where Self: SwiftProtobuf.Message {
@discardableResult
func save(at path: String) -> Result<Void, Error> {
let url = URL(fileURLWithPath: path)
do {
let data = try serializedData()
try data.write(to: url)
return .success(())
} catch {
print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
return .failure(error)
}
}
static func get(fromCache path: String) -> Self? {
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
return try self.init(serializedData: data)
} catch {
print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
return nil
}
}
}
复制代码
After adding the default implementation, we Cachable
already have a field day, as long as meet Codable
or SwiftProtobuf
inside Message
and followed Cachable
on a free persisted.
to sum up
protocol
Absolutely it is used to describe certain features of the weapon , but not the type of restrictions, everything Jieke follow. JSON want to turn model to follow Decodable
, you want to persist an object to follow our Cachable
...
As long as you want to provide some kind of function, the use of protocol
abstraction, it is added to the default implementation, who wants to use this feature follow it, do not want and will not redundant.
Reproduced in: https: //juejin.im/post/5cfb67cb6fb9a07ee958622b