1

I have object like this:

class Human: NSObject {
    var name:String!
    var age:Int!
}

And make instance from object like this:

let instance = Human()  

And set my values like this:

instance.name = "Kirk"
instance.age = 87

And print it like this:

print("name: \(instance.name)") // Kirk
print("age: \(instance.age)") //87

Every things are OK. but now set my values another way like this:

instance.setValue("Kirk", forKey: "name")
instance.setValue(87, forKey: "age")

Get this error for Int dataType:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key age.'

Why this happened?
And How to fix this because i need to using setValue() function.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
reza_khalafi
  • 6,230
  • 7
  • 56
  • 82
  • 1
    The difference is that `instance.name` is accessing the property via native Swift mechanisms, whereas `instance.setValue("Kirk", forKey: "name")` is requires key value coding (KVC), which only works if the types can be represented in Objective-C. As others pointed out, `Int!` cannot be represented in Objective-C, so it cannot participate in KVC. Change `age` from `Int!` to `Int` or `NSNumber!`, and it will work fine. (Clearly if you change it to `Int`, you'll need to make sure it's initialized to a non-`nil` value, presumably with `init` method that takes the value as a parameter.) – Rob May 22 '17 at 09:36
  • Possible duplicate of [Why can I not use KVC from an Objective-C object to a Swift Property?](http://stackoverflow.com/questions/35783888/why-can-i-not-use-kvc-from-an-objective-c-object-to-a-swift-property) – Martin R May 22 '17 at 09:44

2 Answers2

7

Key-value coding (KVC) relies on Objective-C functionality and Int! type is technically an optional value type. Optional value types cannot be represented in Objective-C and that's why the call fails.

You can see the compilation error if you add an explicit dynamic attribute:

class Human: NSObject {
    var name:String!   
    dynamic var age: Int!
}

It would work with Int.

Using implicitly unwrapped optionals in this case is a bad idea anyway. You should have the properties as non-optionals and initialize them in an initializer.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Some optional value types (such as `String!`) can be represented in Obj-C – `Int`'s just problematic because it gets bridged to `NSInteger` and therefore has no way to represent `nil`. – Hamish May 22 '17 at 09:44
  • @Hamish True, there are obvious exceptions where the bridged object is a reference type (`Data`, arrays, dictionaries etc.). – Sulthan May 22 '17 at 09:54
2

Int! can't be represented int Objective-C as other mentioned. This should work

class Human: NSObject {
    var name:String!
    var age : Int;

    init(name:String?, age:Int) {
        self.age = age
        self.name = name
    }
}
Bilal
  • 18,478
  • 8
  • 57
  • 72