Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift-如何使JSONDecoder正确解析类层次结构中的日期数组_Ios_Json_Swift_Swift4_Jsondecoder - Fatal编程技术网

Ios Swift-如何使JSONDecoder正确解析类层次结构中的日期数组

Ios Swift-如何使JSONDecoder正确解析类层次结构中的日期数组,ios,json,swift,swift4,jsondecoder,Ios,Json,Swift,Swift4,Jsondecoder,我有两个类,一个扩展另一个(参见下面的DateDemo和DateDemo2)。 如果我在子对象中有一个[Date],JSONDecoder将无法正确解析它 这是我在iOS上运行的测试类DateDecodeTests。 基本上,我只是尝试了testDateDecodingWithHierarchy测试方法,以通过返回eventsDateTimes3而不是nil 从这两个测试中可以看出,testDateDecoding工作完美,相反,testDateDecodingWithHierarchy在解析e

我有两个类,一个扩展另一个(参见下面的
DateDemo
DateDemo2
)。 如果我在子对象中有一个
[Date]
,JSONDecoder将无法正确解析它

这是我在iOS上运行的测试类
DateDecodeTests
。 基本上,我只是尝试了
testDateDecodingWithHierarchy
测试方法,以通过返回
eventsDateTimes3
而不是
nil

从这两个测试中可以看出,
testDateDecoding
工作完美,相反,
testDateDecodingWithHierarchy
在解析
eventsDateTimes3
字段(该字段仅由子类
DateDemo2
拥有)时存在问题


DateDemo
符合
Decodable
,但没有明确定义
init(from:Decoder)抛出。因此,Swift综合了
init(from:Decoder)的定义,该定义对
DateDemo
的属性进行解码

DateDemo2
继承自
DateDemo
。它添加了一个属性:
eventsDateTimes3
。它没有定义任何初始值设定项。通常,斯威夫特会抱怨缺少初始值设定人。但是,由于新属性既是
var
又是可选的,Swift认为它的默认值为
nil

由于
DateDemo2
的唯一新属性具有默认值,因此Swift适用。您的
DateDemo2
类继承其超类的所有指定初始值设定项。只有一个初始值设定项可继承:合成的
可解码的
初始值设定项。继承的初始化程序将
eventsDateTimes3
初始化为其默认值(
nil
)。这就是继承的初始值设定项的工作方式

您希望Swift通过从
解码器
初始化
事件DateTimes3
,为
DateDemo2
合成一个
可解码的
初始化器,就像它对
DateDemo
所做的那样。但斯威夫特并没有这样做。以下是Itai Ferber(负责
编码
实现的苹果程序员)在

如果编译器能够合成
SuperClass.init(from:)
而不是继承,那么这种情况将得到改善,但如果没有对Swift的协议一致性和继承系统进行重构(并且没有语法来消除“我不提供实现,因为我想继承”与。“我之所以不提供实现,是因为我想

换句话说,有两种合法的情况:

  • 您希望子类继承其超类的初始值设定项,并默认初始化新属性
  • 您希望编译器合成一个对新属性进行解码的初始值设定项
  • 您现在总是得到#1,因为这是添加
    可编码系统之前的全部内容,而且没有语法告诉编译器您想要的是#2

    因此,您需要在
    DateDemo2
    中自己实现
    init(from:)

    class DateDemo2 : DateDemo {
        var eventsDateTimes3 : [Date]?
    
        required init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            eventsDateTimes3 = try container.decode([Date]?.self, forKey: .eventsDateTimes3)
            try super.init(from: decoder)
        }
    
        private enum CodingKeys: String, CodingKey {
            case eventsDateTimes3
        }
    }
    

    DateDemo
    符合
    Decodable
    ,但没有明确定义
    init(from:Decoder)throws
    。因此Swift综合了
    init(from:Decoder)throws
    的定义,该定义对
    DateDemo
    的属性进行解码

    DateDemo2
    继承自
    DateDemo
    。它添加了一个属性:
    eventsDateTimes3
    。它不定义任何初始值设定项。通常,Swift会抱怨缺少初始值设定项。但是,由于新属性既是
    var
    又是可选的,所以Swift认为它的默认值为
    nil

    由于
    DateDemo2
    的唯一新属性具有默认值,因此Swift适用。您的
    DateDemo2
    类继承其超类的所有指定初始值设定项。只有一个初始值设定项可继承:合成的
    可解码的
    初始值设定项。继承的初始值设定项初始化
    eventsDateTimes3
    to它的默认值(
    nil
    )。这就是继承的初始值设定项的工作方式

    您希望Swift通过从
    解码器
    初始化
    事件DateTimes3
    ,为
    DateDemo2
    合成一个
    可解码的
    初始化器,就像它为
    DateDemo2
    所做的那样。但Swift没有这样做。下面是它的想法(负责
    编码
    实现的苹果程序员)在

    如果编译器能够合成
    SuperClass.init(from:)
    而不是继承,那么这种情况将得到改善,但如果没有对Swift的协议一致性和继承系统进行重构(并且没有语法来消除“我不提供实现,因为我想继承”与我不提供实现,因为我想

    换句话说,有两种合法的情况:

  • 您希望子类继承其超类的初始值设定项,并默认初始化新属性
  • 您希望编译器合成一个对新属性进行解码的初始值设定项
  • 您现在总是得到#1,因为这是添加
    可编码系统之前的全部内容,而且没有语法告诉编译器您想要的是#2

    因此,您需要在
    DateDemo2
    中自己实现
    init(from:)

    class DateDemo2 : DateDemo {
        var eventsDateTimes3 : [Date]?
    
        required init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            eventsDateTimes3 = try container.decode([Date]?.self, forKey: .eventsDateTimes3)
            try super.init(from: decoder)
        }
    
        private enum CodingKeys: String, CodingKey {
            case eventsDateTimes3
        }
    }
    

    这取决于您的用例,但另一个解决方法是将公共属性放在协议中,并使用它代替继承。(还允许您使用structs这取决于您的用例,但另一个解决方法是将公共属性放在协议中,并使用它代替继承。)。(也允许你使用structs是的