在 Swift 中使用 PropertyListDecoder 时从 plist 解析浮点值时出现解码错误

Posted

技术标签:

【中文标题】在 Swift 中使用 PropertyListDecoder 时从 plist 解析浮点值时出现解码错误【英文标题】:Decoding Error when parsing float value from plist when using PropertyListDecoder in Swift 【发布时间】:2020-07-30 16:17:04 【问题描述】:

我想在 plist 中存储一些十进制数字并根据要求检索它们。

列表:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>sessionLength</key>
    <integer>1800</integer>
    <key>name</key>
    <string>Sleeping</string>
    <key>generators</key>
    <array>
        <dict>
            <key>dynamic</key>
            <dict>
                <key>amplitude</key>
                <string>40,35,32,30,28,26,22,14,4</string>
                <key>beat</key>
                <string>3.8,3.3,3.0,3.0,2.8,2.6,2.4,2.0,2.0</string>
                <key>carrier</key>
                <string>1:3,1:5,1:6,1:5,1:6,1:5,1:6,1:4,1:3</string>
                <key>type</key>
                <integer>0</integer>
                <key>isoType</key>
                <integer>0</integer>
                <key>depth</key>
                <string>40,40,40,40,40,40,40,40,40</string>
            </dict>
            <key>static</key>
            <dict>
                <key>amplitude</key>
                <real>45</real>
                <key>beat</key>
                <real>2.4</real>
                <key>carrier</key>
                <real>180.6</real>
                <key>depth</key>
                <integer>40</integer>
                <key>type</key>
                <integer>0</integer>
                <key>isoType</key>
                <integer>0</integer>
            </dict>
        </dict>
        <dict>
            <key>dynamic</key>
            <dict>
                <key>amplitude</key>
                <string>40,40,40,40,40,40,40,40,40</string>
                <key>beat</key>
                <string>3.8,3.8,3.8,3.8,3.8,3.8,3.8,3.8,3.8</string>
                <key>carrier</key>
                <string>2:3,1:5,1:6,1:5,1:6,1:5,1:6,1:4,1:3</string>
                <key>type</key>
                <integer>0</integer>
                <key>isoType</key>
                <integer>0</integer>
                <key>depth</key>
                <string>40,40,40,40,40,40,40,40,40</string>
            </dict>
            <key>static</key>
            <dict>
                <key>amplitude</key>
                <integer>50</integer>
                <key>beat</key>
                <real>2</real>
                <key>carrier</key>
                <real>110</real>
                <key>depth</key>
                <integer>80</integer>
                <key>type</key>
                <integer>0</integer>
                <key>isoType</key>
                <integer>0</integer>
            </dict>
        </dict>
        <dict>
            <key>dynamic</key>
            <dict>
                <key>amplitude</key>
                <string>40,40,40,40,40,40,40,40,40</string>
                <key>beat</key>
                <string>3.8,3.8,3.8,3.8,3.8,3.8,3.8,3.8,3.8</string>
                <key>carrier</key>
                <string>1:5,1:5,1:6,1:5,1:6,1:5,1:6,1:4,1:3</string>
                <key>type</key>
                <integer>1</integer>
                <key>isoType</key>
                <integer>2</integer>
                <key>depth</key>
                <string>70,65,65,50,45,40,40,35,30</string>
            </dict>
            <key>static</key>
            <dict>
                <key>amplitude</key>
                <integer>55</integer>
                <key>beat</key>
                <real>4</real>
                <key>carrier</key>
                <integer>180</integer>
                <key>depth</key>
                <integer>90</integer>
                <key>type</key>
                <integer>0</integer>
                <key>isoType</key>
                <integer>0</integer>
            </dict>
        </dict>
    </array>
</dict>
</plist>

原始数据如下所示:

我正在使用可解码协议来检索数据。

struct PresetData: Decodable 
    private enum CodingKeys: String, CodingKey 
        case name, sessionLength, generators
    
    
    let name: String
    let sessionLength: Int
    let generators: [PresetStoredData]


struct PresetStoredData: Decodable 
    private enum CodingKeys: String, CodingKey 
        case `static`, dynamic
    
    
    let `static`: PresetStoredItem
    let dynamic: PresetStoredDynamicItem


struct PresetStoredItem: Decodable 
    private enum CodingKeys: String, CodingKey 
        case amplitude, beat, carrier, depth, type, isoType
    
    
    let amplitude: Float
    let beat: Float
    let carrier: Float
    let depth: Float
    
    let type: Int
    let isoType: Int


struct PresetStoredDynamicItem: Decodable 
    private enum CodingKeys: String, CodingKey 
        case amplitude, beat, carrier, depth, type, isoType
    
    
    let amplitude: String
    let beat: String
    let carrier: String
    let depth: String
    
    let type: Int
    let isoType: Int

结果是“解析的属性列表编号 不适合浮点数。”

编辑:解析方法:

let decoder = PropertyListDecoder()
    return try! decoder.decode(PresetData.self, from: data)

这对我来说没有意义。 知道有什么问题吗?

【问题讨论】:

向下发布屏幕截图。发布您的代码(plist) @LeoDabus plist 是顶部的图片 @Vanya 请直接在问题中发布您的 plist - 不要作为图片。 @LeoDabus 因为我正在使用 PropertyListDecoder() 编辑您的问题并展示您是如何解码的。再次将您的 plist 作为文本发布。 【参考方案1】:

考虑

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>amplitude</key>
    <real>45.0</real>
    <key>beat</key>
    <real>4.2</real>
    <key>carrier</key>
    <real>180.6</real>
</dict>
</plist>

如果你解码:

struct Preset: Decodable 
    let amplitude: Float
    let beat: Float
    let carrier: Float

你会收到

dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "beat", intValue: nil)], debugDescription: "已解析的属性列表编号 不适合 Float。", underlyingError: nil) )

但是如果你把它改成Double,它就可以工作了:

struct Preset: Decodable 
    let amplitude: Double
    let beat: Double
    let carrier: Double

【讨论】:

所以我只想确认一下,是不是 Apple 框架的错误? 对我来说看起来像一个错误。 PropertyListDecoder 未正确处理 FloatDecimalJSONDecoder 可以,但PropertyListDecoder 不行。【参考方案2】:

将浮点类型声明为Double 而不是Float

struct PresetStoredItem: Decodable 
    
    let amplitude: Double
    let beat: Double
    let carrier: Double
    let depth: Double
    
    let type: Int
    let isoType: Int

如果所有键都与结构名称匹配,则可以省略 CodingKeys

【讨论】:

以上是关于在 Swift 中使用 PropertyListDecoder 时从 plist 解析浮点值时出现解码错误的主要内容,如果未能解决你的问题,请参考以下文章

swift 优雅地处理Swift中可本地化的字符串。注意:此代码在Swift 2中,需要在现代Swift中使用更新。

在 Swift 项目中使用 Objective C 类中的 Swift 类

在 Swift 项目中使用 Objective C 类中的 Swift 类

如何在 Swift 中使用 Apple 地图 - 你必须使用 C 还是 Swift 可以?

swift 在swift中使用javascriptcore

swift 在swift中使用枚举练习