Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
406 views
in Technique[技术] by (71.8m points)

Swift optional property using KVC causes crash

I found that using KVC in Swift causes many problems, especially with optional properties.

Here is my specific problem:

Here is a Class named Person. It has a normal property called age,and a Optional(Int) property called ageOptional.

class Person: NSObject {

    var age: Int

    var ageOptional: Int?


    override init(age: Int){

        self.age = 0
    }
}

Now, I use KVC in Person's instance:

//new a instance
var person = Person()

//kvc for normal property: it work well
person.setValue(28, forKeyPath: "age")


//but, this time ,it doesn't work well!!!!
person.setValue(28, forKeyPath: "ageOptional")

The app crashes, and here is the exception:

2015-07-11 11:17:31.546 CFRuntime[4646:607] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key ageOptional.'

I found that, if a property is optional, KVC couldn't find the key. But,I can't find the useful key for an optional property ,and resolve this situation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have already solved the problem perfectly. You cannot use KVC on an Optional Int property, because KVC is Cocoa / Objective-C, and Objective-C cannot see an Optional Int - it is not bridged to Objective-C. Objective-C can only see types that are bridged to Objective-C:

  • class types that are derived from NSObject

  • class types that are exposed with @objc

  • Swift structs that are bridged

Objective-C can also see an Optional wrapping any of those types - almost. It can see an Optional wrapping a bridged struct, but only if that struct is directly bridged. Int is not directly bridged; it is bridged to NSNumber, but not directly (it has to be wrapped). Thus, Objective-C cannot see a Swift member typed as an Int?.

If you really need this to be an Optional, and if you really need to use KVC on it, then declare it as NSNumber?, not Int?. Personally, I would doubt whether either of those things is true; since converting all my apps from Objective-C to Swift, I've found that I don't actually need KVC internally, and that all my KVC-based solutions can be done some other, better way.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...