4

I never used Swift4 before, and dont know how to use KVC in it.
I try to create model with Dictionary, here the code:

class Person : NSObject {
    var name: String = ""
    var age: Int = 0

    init(dict: [String : Any]) {
        super.init()
        self.setValuesForKeys(dict)
    }
}

let dict: [String : Any] = ["name" : "Leon", "age" : 18]
let p = Person(dict: dict)
print(p.name, p.age)

There I get two question:
1. Why dont I using AnyObject? "Leon"and18 was infer to String and Int, does it using in KVC?
2. @objc var name: String = "" , this form is worked, but I can not understand it.

Thanks for all helps.

4
  • Read your code again it says set values for “keys” now where is the key in ‘AnyObject’ . I also don’t understand the second part of the question Commented Dec 7, 2017 at 9:49
  • The above code is wrong. XCode will crash with a uncaught exception. It will work if using @objc. I dont understand how does it work. Commented Dec 7, 2017 at 15:17
  • Please search next time before asking. It took me 10 seconds to find this answer about What is @objc Commented Dec 7, 2017 at 15:24
  • Sorry, this is first time I use StackOverFlow... Commented Dec 8, 2017 at 1:17

3 Answers 3

18

To implement KVC support for a property in Swift 4, you need two things:

  1. Since the current implementation of KVC is written in Objective-C, you need the @objc annotation on your property so that Objective-C can see it. This also means that the property's type needs to be compatible with Objective-C.

  2. In addition to exposing the property to Objective-C, you will need to set up your notifications in order for observers to be notified when the property changes. There are three ways to do this:

For stored properties, the easiest thing to do is to add the dynamic keyword like so:

@objc dynamic var foo: String

This will allow Cocoa to use Objective-C magic to automagically generate the needed notifications for you, and is usually what you want. However, if you need finer control, you can also write the notification code manually:

@objc private static let automaticallyNotifiesObserversOfFoo = false
@objc var foo: String {
    willSet { self.willChangeValue(for: \.foo) }
    didSet { self.didChangeValue(for: \.foo) }
}

The automaticallyNotifiesObserversOf<property name> property is there to signify to the KVC/KVO system that we are handling the notifications ourselves and that Cocoa shouldn't try to generate them for us.

Finally, if your property is not stored, but rather depends on some other property or properties, you need to implement a keyPathsForValuesAffecting<your property name here> method like so:

@objc dynamic var foo: Int
@objc dynamic var bar: Int

@objc private static let keyPathsForValuesAffectingBaz: Set<String> = [
    #keyPath(foo), #keyPath(bar)
]
@objc var baz: Int { return self.foo + self.bar }

In the example above, an observer of the baz property will be notified when the value for foo or the value for bar changes.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your help. I will research deep into it. Can I answer last question? Which document should I learn more for KVC in Swift? I am not good at for Apple`s English document...
@Ben Here are Apple's documents on KVC and KVO. Unfortunately they mainly focus on Objective-C, so some understanding of how the two languages interact will help to understand them.
Appreciate again!! I will research Swift in Cocoa, then back to the feature of Swift. Thank u my friend!
0

Everything was right for me but still I was getting this error, then I solved it by

  • Enabling the "Inherit module from Target" in the Identity Inspector. or
  • Giving the module(usually folder name/group name) in which it is present from the Identity Inspector under Custom Class

Comments

-1
  1. your code

    var name: String = "" var age: Int = 0

    you can write the same code like this, when you are sure about its type.

    var name = "" var age = 0

    Any is generally used for all types(function types and optional types), while AnyObject is used for Class types.

  2. @objc have different meaning, when you use @objc in your swift class, that code is available in objective-c. You should use @objc attribute to specify same as objective-c class, in result older archives can be replaced by new swift class.

1 Comment

thanks for the answer. Could u show me how does KVC usually use in Swift 4.0?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.