一段时间以来,我一直在试图解决这个问题,但是除了:: p之外,我还无法理解KVC的优势。
除了上面提到的两种情况外,我不确定使用KVC是否有任何优势(我知道我可能是错的),但是我找不到一个!
请考虑以下代码:
class Profile: NSObject {
@objc var firstName: String
var lastName: String
init(firstName: String,lastName: String) {
self.firstName = firstName
self.lastName = lastName
super.init()
}
}
let profile1 = Profile(firstName: "John", lastName: "Doe")
profile1.firstName // returns String "John"
profile1.value(forKey: "firstName") // returns Optional<Any>
let firstNameKey = \Profile.firstName
profile1[keyPath: firstNameKey] /* returns String "John" */
我的意思是为什么我要使用:
让firstNameKey = \ Profile.firstName
profile1 [keyPath:firstNameKey] / *返回字符串“ John” * /
而不是:
profile1.firstName //返回字符串“ John”
如果某人有一些代码示例/示例,那么如果他们可以使用swift对其进行解释,那将会很棒(因为我的Objective-C不好)
答案 0 :(得分:2)
您使用的示例并非使用 KVC 或 keyPath 本身的最佳情况。
使用协议时, keyPath 的真正威力将得到释放。让我举一个例子-
假设您有一个协议Identifiable
,该协议只有一个成员-id
。符合此要求的每种类型都必须使用id
属性来唯一标识它。
protocol Identifiable {
var id: Int { get }
}
struct Person: Identifiable {
var id: Int
var name: String
}
在这里,具有成员Person
的{{1}}类型听起来不太好。考虑另一个-
id
在这里,struct Book: Identifiable {
var id: Int
var title: String
var author: String
}
可以唯一标识一本书,但这听起来并不好。
这是 keyPath 发挥作用的地方。
您可以使用某些名称在协议内定义成员,然后让符合条件的类型为该特定协议成员写自己的名称。符合条件的类型可以映射或告诉编译器,它们的特定成员是使用 keyPath 替换协议内部的成员。
id
另一个优点是,符合条件的类型可以具有protocol Identifiable {
associatedtype ID
static var id: WritableKeyPath<Self,ID> { get }
}
struct Person: Identifiable {
static var id = \Person.socialSecurityNumber
var socialSecurityNumber: Int
var name: String
}
struct Book: Identifiable {
static var id = \Book.isbn
var isbn: String
var title: String
var author: String
}
func printID<T: Identifiable>(aType: T) {
print(aType[keyPath: T.id])
}
printID(aType: Person(socialSecurityNumber: 1234, name: "Shubham Bakshi"))
printID(aType: Book(isbn: "qwertyui", title: "The Theory of Everything", author: "Stephen W. Hawking"))
,id
,String
任何类型的Int
,而不是仅Int
(以前的情况)>
如果您只想给id
指定一种特定类型,只说Int
,则可以用此协议代替我们的协议定义-
protocol Identifiable {
static var id: WritableKeyPath<Self,Int> { get }
}
这将强制符合条件的类型使用Int
代替其id
。