How do I use Key-Value Coding in Swfit 4.0?

拥有回忆 提交于 2019-12-03 17:08:45

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.

  1. In swift all class inherit NSObject are KVC compliant, there is type not instance, Any for type , AnyObject for instance

  2. @objc is for objective-c class call it.

A key-path expression accepts property references and chained property references, such as \Animal.name.count

class Animal: NSObject {
    @objc var name: String

    init(name: String) {
        self.name = name
    }
}

let llama = Animal(name: "Llama")
let nameAccessor = \Animal.name
let nameCountAccessor = \Animal.name.count
llama[keyPath: nameAccessor]
// "Llama"
llama[keyPath: nameCountAccessor]
// "5"

Using Swift with Cocoa and Objective-C there are detail

  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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!