Closed AhmedZahraz closed 9 years ago
This looks like a swift bug / missing feature where there is no workaround possible. I created a unit test for this. I will do some more tests and then push this test to github. Maybe you can confirm that the test that I created is how you wanted to use generics?
The problem is that a generic class is not key value coding complient. So it's not possible to set any of the properties using yourObject.setValue(value, forKey: key) Then for some reason it's also not executing the setValue forUndefinedKey on the object itself. When adding a base class with a setValue forUndefinedKey, then the calls will come in there.
I will create an Apple bug report for this.
class Workarounds2Tests: XCTestCase {
func testGenerics() {
let json:String = "{\"test\":\"test\", \"data\":\"data\"}"
let a = A<NSString>(json:json)
XCTAssertEqual(a.test, "test", "test should contin test")
XCTAssertEqual(a.data as! String, "data ", "data should contin data")
}
}
public class A<T where T:NSObject>: GenericsBase {
var test : String = ""
var data: T = T()
// Handling the setting of non key-value coding compliant properties
override public func setValue(value: AnyObject!, forUndefinedKey key: String) {
switch key {
case "test":
test = value as! String
case "data":
data = value as! T
default:
println("---> setValue for key '\(key)' should be handled.")
}
}
}
public class GenericsBase: EVObject {
override public func setValue(value: AnyObject!, forUndefinedKey key: String) {
println("---> GenericsBase: setValue for key '\(key)' should be handled.")
}
}
Unit test can be found at: https://github.com/evermeer/EVReflection/blob/master/EVReflection/EVReflectionTests/SwiftGenericsBug.swift
An Apple bug report has been posted with the ID 22218794
I succeeded creating a workaround for this. I will push an update later today. For solving this issue you will get code like this:
class WorkaroundSwiftGenericsTests: XCTestCase {
func testGenerics() {
let json:String = "{\"test\":\"test\", \"data\":\"data\"}"
let a = MyGenericObject<NSString>(json: json)
XCTAssertEqual(a.test, "test", "test should contin test")
XCTAssertEqual(a.data as! String, "data", "data should contin data")
}
}
// Only put the generic properties in this class. put the rest in a base class
public class MyGenericObject<T where T:NSObject>: MyGenericBase, EVGenericsKVC {
var data: T = T()
public func genericSetValue(value: AnyObject, forKey key: String) {
switch key {
case "data":
data = value as! T
default:
println("---> setValue '\(value)' for key '\(key)' should be handled.")
}
}
}
// Put the rest of the properties in a base class like this. Otherwise you have to handle each in the genericSetValue
public class MyGenericBase: EVObject {
var test : String = ""
}
I have pushed the update to GitHub. You have to use version 2.5.1 if you want to implement this workaround.
i have renamed the method in the protocol. Now instead of implementing genericSetValue you can use override public func setValue(value: AnyObject!, forUndefinedKey key: String) { So now it's the same as the other situations where key value coding is not supported.
Since this is a Swift limitation / bug and there is a workaround which is added as a unit test, I am closing this issue.
Thanks @evermeer it's working now !
Hi, I'im trying to parse jsonString to an object that contains a generic type but it's not working. This is my example :
public class A: EVObject {
}
public class B: EVObject {
var test3 : String = "" var test4 : String = ""
}