plist 中 CMTime 和 CMTimeRange 的现代方式使用 Swift
Modern way of CMTime and CMTimeRange in plist using Swift
在 plist 中存储 CMTime 和 CMTimeRange 等对象的最'modern' Swift 方法有哪些?我尝试了以下方法。字典对象存储在 plist 中。
dictionary["timeRange"] = NSValue(timeRange: timeRange)
还有,
dictionary["timeRange"] = CMTimeRangeCopyAsDictionary(timeRange, allocator: kCFAllocatorDefault)
有人指出,第一种方法的问题是 NSValue 更像是 Objective-C 类的东西,它需要先存档,然后才能存储在 plist 中。第二种方法是基于字典的方法,其中 timeRange 存储为 CFDictionary 但与 plist 兼容,无需存档。但离Swift!
更远的是CFDictionary
那么使 CMTimeRange 属性 列表可序列化的现代方法是什么?
将 PropertyListEncoder
/PropertyListDecoder
与 Codable
模型类型一起使用。 CMTime
和 CMTimeRange
默认不符合 Codable
,所以你需要自己添加一致性。
extension CMTime: Codable {
enum CodingKeys: String, CodingKey {
case value
case timescale
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let value = try container.decode(CMTimeValue.self, forKey: .value)
let timescale = try container.decode(CMTimeScale.self, forKey: .timescale)
self.init(value: value, timescale: timescale)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(value, forKey: .value)
try container.encode(timescale, forKey: .timescale)
}
}
extension CMTimeRange: Codable {
enum CodingKeys: String, CodingKey {
case start
case duration
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let start = try container.decode(CMTime.self, forKey: .start)
let duration = try container.decode(CMTime.self, forKey: .duration)
self.init(start: start, duration: duration)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(start, forKey: .start)
try container.encode(duration, forKey: .duration)
}
}
struct Model: Codable {
let time: CMTime
let timeRange: CMTimeRange
}
let model = Model(time: CMTime.invalid, timeRange: CMTimeRange(start: CMTime(), end: CMTime()))
do {
let encodedData = try PropertyListEncoder().encode(model)
let decodedData = try PropertyListDecoder().decode(Model.self, from: encodedData)
print(decodedData)
} catch {
print(error)
}
在 plist 中存储 CMTime 和 CMTimeRange 等对象的最'modern' Swift 方法有哪些?我尝试了以下方法。字典对象存储在 plist 中。
dictionary["timeRange"] = NSValue(timeRange: timeRange)
还有,
dictionary["timeRange"] = CMTimeRangeCopyAsDictionary(timeRange, allocator: kCFAllocatorDefault)
有人指出,第一种方法的问题是 NSValue 更像是 Objective-C 类的东西,它需要先存档,然后才能存储在 plist 中。第二种方法是基于字典的方法,其中 timeRange 存储为 CFDictionary 但与 plist 兼容,无需存档。但离Swift!
更远的是CFDictionary那么使 CMTimeRange 属性 列表可序列化的现代方法是什么?
将 PropertyListEncoder
/PropertyListDecoder
与 Codable
模型类型一起使用。 CMTime
和 CMTimeRange
默认不符合 Codable
,所以你需要自己添加一致性。
extension CMTime: Codable {
enum CodingKeys: String, CodingKey {
case value
case timescale
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let value = try container.decode(CMTimeValue.self, forKey: .value)
let timescale = try container.decode(CMTimeScale.self, forKey: .timescale)
self.init(value: value, timescale: timescale)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(value, forKey: .value)
try container.encode(timescale, forKey: .timescale)
}
}
extension CMTimeRange: Codable {
enum CodingKeys: String, CodingKey {
case start
case duration
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let start = try container.decode(CMTime.self, forKey: .start)
let duration = try container.decode(CMTime.self, forKey: .duration)
self.init(start: start, duration: duration)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(start, forKey: .start)
try container.encode(duration, forKey: .duration)
}
}
struct Model: Codable {
let time: CMTime
let timeRange: CMTimeRange
}
let model = Model(time: CMTime.invalid, timeRange: CMTimeRange(start: CMTime(), end: CMTime()))
do {
let encodedData = try PropertyListEncoder().encode(model)
let decodedData = try PropertyListDecoder().decode(Model.self, from: encodedData)
print(decodedData)
} catch {
print(error)
}