繁体   English   中英

如何在 Swfit 4.0 中使用键值编码?

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

之前没用过Swift4,不知道里面怎么用KVC。
我尝试使用字典创建模型,代码如下:

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)

我有两个问题:
1. 为什么我不使用AnyObject "Leon"18是推断StringInt ,它在 KVC 中使用吗?
2. @objc var name: String = "" ,这种形式是有效的,但我看不懂。

感谢所有帮助。

要在 Swift 4 中为属性实现 KVC 支持,您需要做两件事:

  1. 由于当前 KVC 的实现是用 Objective-C 编写的,因此您需要在属性上添加@objc注释,以便 Objective-C 可以看到它。 这也意味着属性的类型需要与 Objective-C 兼容。

  2. 除了向 Objective-C 公开属性之外,您还需要设置通知,以便在属性更改时通知观察者。 有三种方法可以做到这一点:

对于存储属性,最简单的方法是添加dynamic关键字,如下所示:

@objc dynamic var foo: String

这将允许 Cocoa 使用 Objective-C 魔法为您自动生成所需的通知,并且通常是您想要的。 但是,如果需要更精细的控制,也可以手动编写通知代码:

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

automaticallyNotifiesObserversOf<property name>属性在那里向 KVC/KVO 系统表明我们自己处理通知并且 Cocoa 不应该尝试为我们生成它们。

最后,如果你的属性没有被存储,而是依赖于其他一些属性,你需要实现一个keyPathsForValuesAffecting<your property name here>方法,如下所示:

@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 }

在上面的示例中,当foo的值或bar的值发生变化时,将通知baz属性的观察者。

  1. 在swift中,所有类继承NSObject都符合KVC,类型不是实例,Any代表类型,AnyObject例如

  2. @objc是针对objective-c类调用它的。

键路径表达式接受属性引用和链接属性引用,例如\\ 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"

使用Swift与Cocoa和Objective-C有详细说明

一切都适合我,但我仍然收到此错误,然后我解决了

  • 在身份检查器中启用“从目标继承模块”。 要么
  • 从自定义类下的身份检查器中提供模块(通常是文件夹名称/组名称)
  1. 你的代码

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

    当您确定其类型时,您可以像这样编写相同的代码。

    var name = "" var age = 0

    Any 一般用于所有类型(函数类型和可选类型),而 AnyObject 用于 Class 类型。

  2. @objc 有不同的含义,当您在 swift 类中使用 @objc 时,该代码在objective-c 中可用。 您应该使用@objc 属性指定与objective-c 类相同的属性,结果旧的存档可以被新的swift 类替换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM