Closed sagits closed 8 years ago
Hi, since there is a property named objectFull the function setValue forUndefined key will not be called for the key objectFull. (the key is not undefined.)
I think the best approach for this is by creating a base class for your objectFull objects. EVReflection has support for this. You can override the function getSpecificType where you make sure the correct type is returned. There is a unit test available that will show you how this can be used. See: https://github.com/evermeer/EVReflection/blob/7b4b3b31f3f9a5a3166cc32acc5501d4bd3ae2c9/EVReflection/EVReflectionTests/EVRelfectionEnheritanceTests.swift#L70-L70 make sure you base the type selection on what's in the dictionary and not based on existing properties in the object. The test will show you how you can do this.
Just let me know of you have any questions
Hi, thank you, it worked. How can i access the returned object? I have tried with objectFull as! TaskModel but it gives an exception. Using objectFull.valueForKey(keyName) worked, but is there another way? Thank you in advance.
Hi @sagits, Are you still using the setValue forKey for setting the fullObject? If so, then It will be called with a dictionary and not with a parsed object. You could still set it with something like: objectFull = TaskObject(dictionary: value)
If you are using the getSpecificType code, then the object should already be set correctly.
Hi @evermeer. Im using the getSpecificType() approach. But on the editor the fullObject is still a FullObjectModel, and although on compile time it has all the TaskModel or SaleModel fields, its still declared as as FullObjectModel on the debugger (because the property type is FullObjectModel).
I just added some extra checks in the inheritance test. There it works. Here is the code that I now have in place. As you can see I go from object to json to an object again and then test if the values are as the original object.
func testEnheritance() {
// Build up the original object
let quz = Quz()
quz.fooBar = Bar()
quz.fooBaz = Baz()
quz.fooFoo = Foo()
quz.fooArray = [Bar(), Baz(), Foo()]
// The object JSON
let json = quz.toJsonString()
print("Original JSON = \(json)")
// Deserialize a new object based on that JSON
let newObject = Quz(json: json)
XCTAssertEqual((newObject.fooBar as? Bar)?.justBar, "For bar only", "fooBar is not Bar?")
XCTAssertEqual((newObject.fooBaz as? Baz)?.justBaz, "For baz only", "fooBaz is not Baz?")
XCTAssertEqual(newObject.fooArray.count, 3, "array should contain 3 objects")
if newObject.fooArray.count == 3 {
XCTAssertEqual((newObject.fooArray[0] as? Bar)?.justBar, "For bar only", "fooBar is not Bar?")
XCTAssertEqual((newObject.fooArray[1] as? Baz)?.justBaz, "For baz only", "fooBaz is not Baz?")
XCTAssertEqual(newObject.fooArray[2].allFoo, "all Foo", "should just be a Foo?")
}
// The new object JSON
let newJson = newObject.toJsonString()
print("New JSON = \(newJson)")
// The original and new JSON Should be the same
XCTAssertEqual(json, newJson, "The json should be the same after serialisation and deserialization")
}
}
class Quz: EVObject {
var fooArray: Array<Foo> = []
var fooBar: Foo?
var fooBaz: Foo?
var fooFoo: Foo?
}
class Foo: EVObject {
var allFoo: String = "all Foo"
// What you need to do to get the correct type for when you deserialize inherited classes
override func getSpecificType(dict: NSDictionary) -> EVObject {
if dict["justBar"] != nil {
return Bar()
} else if dict["justBaz"] != nil {
return Baz()
}
return self
}
}
class Bar : Foo {
var justBar: String = "For bar only"
}
class Baz: Foo {
var justBaz: String = "For bad only"
}
It worked, my mistake. Thank you for helping.
Hi, i have the following class:
I know i could solve this with generics, but i receive an array of events from my server, so i cant instantiate it with generics. This approach (NSObject) isnt working. May you help me please? Thanks in advance.