Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/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
Generics Swift通用对象/JSON序列化_Generics_Serialization_Swift - Fatal编程技术网

Generics Swift通用对象/JSON序列化

Generics Swift通用对象/JSON序列化,generics,serialization,swift,Generics,Serialization,Swift,tl;dr您是否可以使用一致性协议的初始值设定方法对对象进行常规实例化,同时仍保留对象的预期类型?我现在尝试的是seg对编译器进行错误处理 在我正在编写的一个库中,我试图使用Swift有限的内省功能实现一般序列化/反序列化对象的目标 下面是使用反射设置变量值的全局函数的代码。如果找到字典,它将尝试协调嵌套构造: func model__setValue<T where T: NSObject, T: Serializable>(value: AnyObject, forSerial

tl;dr您是否可以使用一致性协议的初始值设定方法对对象进行常规实例化,同时仍保留对象的预期类型?我现在尝试的是seg对编译器进行错误处理


在我正在编写的一个库中,我试图使用Swift有限的内省功能实现一般序列化/反序列化对象的目标

下面是使用反射设置变量值的全局函数的代码。如果找到字典,它将尝试协调嵌套构造:

func model__setValue<T where T: NSObject, T: Serializable>(value: AnyObject, forSerializationKey key: String, model m: T) {
    let varNames = object__getVarNames(mirror: reflect(m)) // Gets a list of this object's variable names
    if let i = find(m.serializationKeys, key) {
        if value is [String : AnyObject] {
            // This allows us to have nested dictionary representations
            // of Serializable constructs and have them init properly
            let t1 = reflect(m)[i].1.valueType as NSObject.Type
            if t1 is Serializable.Type {
                let t2 = t1 as Serializable.Type
                let finalObj = t2(dictionary: value as [String : AnyObject]) // Segmentation fault: 11
                m.setValue(finalObj, forKey: varNames[i])
            }
        } else {
            m.setValue(value, forKey: varNames[i])
        }
    }
}
func model\uuu setValue(值:AnyObject,forSerializationKey:String,model m:T){
让varNames=object\uu getVarNames(mirror:reflect(m))//获取此对象的变量名列表
如果让i=find(m.serializationKeys,key){
如果值为[String:AnyObject]{
//这允许我们使用嵌套的字典表示
//一个可序列化的构造,并使它们正确初始化
设t1=reflect(m)[i].1.valueType为NSObject.Type
如果t1是可序列化的。请键入{
将t2=t1设为可序列化类型
设finalObj=t2(dictionary:value为[String:AnyObject])//分段错误:11
m、 setValue(finalObj,forKey:varNames[i])
}
}否则{
m、 setValue(value,forKey:varNames[i])
}
}
}
有几件事需要解释:

  • Serializable
    是一种协议定义方法,包括init(字典)。它被希望(反)序列化的对象采用
  • Serializable
    还指定“序列化键”的计算属性或字符串列表,这些字符串用作对象变量的字典键,并且必须是变量名到序列化键的一对一映射。为什么要这样做?有时,API调用返回的键已经没有意义了(schema rot?),或者我只是想用不同的方式命名变量,因为我不太喜欢下划线
  • 模型必须既是一个
    NSObject
    ,又符合
    Serializable
    。为什么?为了实现这样的泛型,我需要能够在不提前知道对象的标识符的情况下写入对象的字段。斯威夫特没有办法在本机实现这一点,因此子类化NSObject是一个很好的折衷方案。为什么不使用具有这些特性的根对象呢
  • 我的目标是从JSON表示中简单、低开销地构造对象(即使使用不同的键和变量名,即使使用嵌套对象)。因此,给一个对象它的密钥列表,让协议的
    init
    调用另一个泛型构造函数,该构造函数迭代对象的变量并每次调用它。砰。这就是全部。现在,您可以解析所有(JSON)API中的所有内容,并且只编写很少的解析逻辑或不编写任何解析逻辑。我希望同样的方法也适用于序列化程序,因此
    toDictionary
    也只需要一个泛型方法调用

    在这个函数中,我们使用反射动态设置对象的值。首先,我们确保这是要在对象上设置的有效键。接下来,我们确定要设置的值是否是字典。如果是,我想获取目标对象的类型,看看它实际上是否也是可序列化的类型。如果该字段是,我们可以使用这个字典递归地构造它(这不适用于稍后的解释)。如果不是,或者该值根本不是字典,只需使用Cocoa的setValue:forKey:method

    唉,我无法让嵌套对象部分正常工作,我还没有弄清楚我试图做的是不可能的,还是我只是做错了。我还担心我的
    let finalObj
    行无效,尽管Xcode上没有错误。我的思维过程就是调用
    Serializable
    init
    构造函数,然后继续我的快乐之路。我认为问题在于Swift的静态类型特性,编译器实际上不知道init将返回什么最终类型(尽管Xcode高亮显示该行中的
    t2
    ,颜色与关键字相同…)。我不确定是否有一种方法可以说t1是一个同样符合可序列化的
    NSObject
    。我想我现在尝试的是
    t2
    ,而cast正在丢失类型信息,从而导致seg错误,尽管在我真正开始构建之前,Xcode不会抱怨它


    我尝试了几种方法来协调这个嵌套的
    Serializable
    问题,但没有找到解决方案。有人能帮忙吗

    看看这篇文章,其他人做了一些和你尝试的一样的事情。它可能会对你有所帮助,或者它可能正是你想要的:

    我理解您试图做什么,但是
    Serializable
    看起来像什么?
    Serializable
    看起来像什么,并且通用函数使它真正起作用。在这段代码中,我做了一些变通,因为它不是100%通用的,正如上面所描述的。看看SwiftyJSON?我已经研究过它(尽管承认我从未克隆和使用过它)。但我不认为它满足了我想做的事情。我有点遵循的方法,给一个想法。你链接这个问题从一段时间以前。编译器崩溃已在Xcode 7b2中修复,这解决了我的问题,因此它也可能解决您的问题。