使用Swift在plist中使用CMTime和CMTimeRange的现代方法

问题描述

在plist中存储诸如CMTime和CMTimeRange之类的对象的最“现代” Swift方法是什么?我尝试了以下方法。字典对象将存储在plist中。

  dictionary["timeRange"] =  NSValue(timeRange: timeRange)

还有

  dictionary["timeRange"] = CMTimeRangeCopyAsDictionary(timeRange,allocator: kCFAllocatorDefault)

有人指出,第一种方法的问题是NSValue更像是Objective-C的东西,需要对其进行存档,然后才能将其存储在plist中。第二种方法是基于字典的方法,其中timeRange存储为CFDictionary,但与plist兼容,无需存档。但是CFDictionary离Swift更远了!

那么使CMTimeRange属性列表可序列化的现代方法是什么?

解决方法

PropertyListEncoder / PropertyListDecoderCodable模型类型一起使用。 CMTimeCMTimeRange在默认情况下不符合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)
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...