tl; dr Can you generally create an instance of an object using the initializer method of the corresponding protocol, and also save the target object? Now I am trying to compromise the compiler.
In the library I'm writing, I am trying to achieve the goal of generating serialization / deserialization of objects using the limited Swift introspection capabilities.
Here is the code for a global function that sets a variable using reflection. He tries to reconcile for nested constructions if he finds a dictionary:
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 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]) } } }
A few things to explain:
Serializable is a protocol that defines methods, including init (a dictionary). It is accepted by objects that want to be (de) serialized.Serializable also defines the computed property "serialization keys" or a list of strings that are used as dictionary keys for object variables and should be a one-to-one mapping of variable names for serialization keys. Why do this? Sometimes the API calls return keys that really don't make sense (rot? Schema), or I just want to name the variable in different ways, since I don't really like to underline underscores too much.- The model should be like
NSObject and match Serializable . What for? To get such generics, I needed the ability to write to the fields of objects without knowing their identifiers ahead of time. Swift has no way to do this initially, so the NSObject subclass is a good compromise. Why not have a root object with these features at all?
My goal in this is a silly easy, low overhead construction of objects from their JSON representation (even with different keys and variable names, even with nested objects). Therefore, give the object its list of keys and make the init protocol a call to another universal constructor function that iterates over the object variables and calls it each time. Bam. All this. Now you can parse all things from all (JSON) APIs and write very little or no logic analysis. I would like the same to apply to the serializer, so toDictionary also requires only one call to the general method.
In this function, we dynamically set the value of an object using reflection. Firstly, we are sure that this is a valid key for installation on the object. Then we determine if the value we want to set is a dictionary. If so, I want to capture the type of the target to see if it really matches the type of Serializable . If this is a field, we can use this dictionary to construct it recursively (this does not work as explained in the near future). If this is not the case, or the value is not a dictionary at all, just use Cocoa setValue: forKey: method.
Alas, I cannot make part of the embedded object work completely correctly, and I did not understand that what I am trying to do is simply impossible or if I just do it wrong. I am also worried that my let finalObj line is invalid, despite the absence of an Xcode error. My thought process is just a call to the Serializable init constructor and continue my fun journey. I assume the problem is that this is the static typed nature of Swift, and the compiler does not actually know which final type will be returned by init (although Xcode highlights t2 in this line the same color as the keywords ...). I'm not sure if there is a way to say t1 is an NSObject that also matches Serializable . I think I'm trying to do t2 , and casting will lose type information and thus cause a seg error, although Xcode doesn't complain about it until I'm actually going to build.
I tried several ways to reconcile this nested Serializable thing and could not find a solution. Can anyone help?
generics serialization swift
Stefan arambasich
source share