Swift4中自动解码的性能

在很多情况下,您将面临通过网络发送或接收数据(或仅保存/加载文件中的自定义对象)的问题。 而且,当然,有几种不同的技术可以对JSON进行序列化/反序列化-您可以自己完成操作,也可以使用第三方框架。

最后,Apple提供了新的编码和解码自定义类型。 到目前为止,您的数据类型变得可编码和可解码,以与JSON等外部表示兼容。 它提出了极其简单明了的方法,减少了代码并节省了时间。 是不是很酷? 好…

测量解码自定义类型

不幸的是,我们没有生活在一个完美的世界中。 有时需要处理带有很多胖对象的胖JSON,而我们对此无能为力。

让我们比较一下通过新的API自动解码自定义类型和手动解码(意味着完全手动解码,而不是“ init(来自解码器:解码器)”)。

我已经创建了简单的结构`Writer`。 它符合`Codable`,并且可以用`JSONDecoder`解码。 也可以使用执行手动解码的init(dictionary :[String:Any] `对该对象进行解码。

测试环境和配置:

  • iPhone 7,iOS 11.2
  • 构建配置:发布
  • 优化级别:[-Ofast]
  struct作者:可编码{ 
var名称:字符串?
var email:字符串?
var contact:字符串?
var years:整数?
var isPublic:布尔?
}

苹果还为支持“可编码”的对象提供了自己的“手动编码和解码”实现。 如文档中所述:

如果您的Swift类型的结构与其编码形式的结构不同,则可以提供EncodableDecodable的自定义实现,以定义自己的编码和解码逻辑。

因此,为了测试结构,添加了扩展名`init(from解码器:Decoder)`。

 扩展作家:可解码{ 
枚举CodingKeys:字符串,CodingKey {
案例名称
案例电子邮件
案例联系
案例年
案例是公开的
}
init(来自解码器:解码器)抛出{
让值=尝试解码器。容器(keyedBy:CodingKeys.self)
名称=尝试? values.decode(String.self,forKey:.name)
电子邮件=尝试? values.decode(String.self,forKey:.email)
联系人=试试? values.decode(String.self,forKey:.contact)
年=尝试? values.decode(Int.self,forKey:.years)
isPublic =尝试吗? values.decode(Bool.self,forKey:.isPublic)
}
}

结果非常令人惊讶。 对于非常简单的模型,使用init(来自解码器:Decoder)进行解码比自动解码和手动解码的实现要花费更多时间。


让我们尝试解码更复杂的对象。 为此,我创建了一个新的`ComplexWriter`,它基本上只包含更多属性,其中一些也是自定义类型。

  struct ComplexWriter:可编码{ 
var名称:字符串?
var email:字符串?
var contact:字符串?
var isPublic:布尔?
varbornDate:双倍?
var deadDate:Double?
var职业:字符串?
var国籍:字符串?
var国籍:字符串?
var genre:[String]?
var chirdren:诠释?
var notableWorks:[String]?
var allWorks:[图书]?
}
结构书:可编码{
var标题:字符串?
var系列:字符串?
var genre:字符串?
var发表:Double?
var translationLanguages:[String]?
var改编:[String]?
}

对于“ ComplexWriter”,还添加了“ init(来自解码器:解码器)”的解码。 我不会在此处提供此代码,以节省空间和您的时间。 但是您可以在GitHub上找到它,链接在其他信息部分提供。

下面添加了使用`init(来自解码器:Decoder)扩展名对`ComplexWriter`进行解码的测试。

笔记:

  1. 如果某些字段可能缺失并且不是必需的,则最好将其设置为可选。 在其他情况下,对象将不会被解码。
  2. 如果您的对象包含嵌套类型,则它们也应该是“可编码的”
  3. 总是考虑演员。 例如,您的对象具有属性“ count”,即Int。 但是您的API提供商将“ count”值作为字符串发送给您(例如{“ count”:“ 11”}),这不会产生魔力-自动解码将无法正确解码。

有关编码和解码自定义类型的其他信息:

  • https://developer.apple.com/videos/play/wwdc2017/212/
  • https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
  • 此测试的源代码位于:https://github.com/ZippiCoder/Samples/tree/master/Codable/CodableJson

关于性能的问题之所以出现,是因为以前有解析大型xml文件并在DOM,SAX或StAX(文件包含大约2万个胖对象的信息)之间进行选择的经验。 这是对解码自定义类型进行的非常简短的实验。 如您所见,对于小型和简单的模型,使用自动解码的方法比手动解码的工作速度更快甚至更快。 对于大型和复杂的模型,情况恰恰相反-自动解码比手动解码需要更多的时间。 使用`init(from解码器:Decoder)`进行手动解码效果很好,可以为您完成很多工作,但是不幸的是,这需要花费一定的成本。

始终尝试选择最适合您的项目的方法。 不要害怕花费一些时间并检查几种不同的方法。 确实可以在将来节省大量时间。

谢谢阅读!