KeyValueCoding
提供了一种机制,允许你通过字符串键或键路径间接访问纯 Swift struct
或 class
实例的属性。
访问实例属性值的 KeyValueCoding
协议的基本方法是通过字符串键或键路径进行下标操作。 为了使你的类型符合键值编码,只需从该协议继承即可,例如:
import KeyValueCoding
struct Resolution: KeyValueCoding {
let width: Int
let height: Int
}
var resolution = Resolution(width: 640, height: 480)
resolution["width"] = 1920
resolution["height"] = 1080
print(resolution) // Prints: Resolution(width: 1920, height: 1080)
注意:实例变量必须声明为
var
,否则会出现以下错误:Cannot use mutating getter on immutable value
(无法对不可变值使用可变 getter)。
同样适用于键路径:
resolution[\Resolution.width] = 2560
resolution[\Resolution.height] = 1440
print(resolution) // Prints: Resolution(width: 2560, height: 1440)
您还可以以相同的方式读取属性值:
if let width: Int = resolution[\Resolution.width], let height: Int = resolution[\Resolution.height] {
print("\(width)x\(height)") // Prints: 2560x1440
}
以下属性可以以一致的方式用于类和结构体,包括:
let
和变量 var
属性。lazy
, @objc
和可选属性。public
、internal
、private
等。enum
、struct
、class
、元组等。但是有一些 **限制**:
willSet
和 didSet
观察器。weak
、unowned
和属性包装器。KeyValueCoding
可以通过字符串键(“relationship.property”)或键路径访问关系属性,例如:
import KeyValueCoding
struct Resolution {
let width: Int
let height: Int
}
class VideoMode: KeyValueCoding {
let name: String
let resolution: Resolution
init(name: String, resolution: Resolution) {
self.name = name
self.resolution = resolution
}
}
var videoMode = VideoMode(name: "HD", resolution: Resolution(width: 1920, height: 1080))
print("\(videoMode.name) - \(videoMode.resolution.width)x\(videoMode.resolution.height)")
// Prints: HD - 1920x1080
videoMode[\VideoMode.name] = "4K"
videoMode[\VideoMode.resolution.width] = 3840
videoMode[\VideoMode.resolution.height] = 2160
print("\(videoMode.name) - \(videoMode.resolution.width)x\(videoMode.resolution.height)")
// Prints: 4K - 3840x2160
注意:您的父实例可以访问其子级的属性,而无需子级符合
KeyValueCoding
协议。
从继承类继承的属性也可以通过 KeyValueCoding
协议访问。
import KeyValueCoding
class Mode {
let name: String
init(name: String) {
self.name = name
}
}
class VideoMode: Mode, KeyValueCoding {
let frameRate: Int
init(name: String, frameRate: Int) {
self.frameRate = frameRate
super.init(name: name)
}
}
var videoMode = VideoMode(name: "HD", frameRate: 30)
print("\(videoMode.name) - \(videoMode.frameRate)fps")
// Prints: HD - 30fps
videoMode[\VideoMode.name] = "4K"
videoMode[\VideoMode.frameRate] = 25
print("\(videoMode.name) - \(videoMode.frameRate)fps")
// Prints: 4K - 25fps
您可以从 KeyValueCoding
继承任何协议,然后该协议的所有实例都将可以访问以读取和写入其属性。
import KeyValueCoding
protocol Size: KeyValueCoding {
var width: Int { get }
var height: Int { get }
}
struct Resolution: Size {
let width: Int
let height: Int
}
var resolution: Size = Resolution(width: 1920, height: 1080)
print(resolution)
// Prints: Resolution(width: 1920, height: 1080)
resolution[\Resolution.width] = 3840
resolution[\Resolution.height] = 2160
if let width: Int = resolution[\Resolution.width], let height: Int = resolution[\Resolution.height] {
print("\(width)x\(height)")
// Prints: 3840x2160
}
此外,您可以纯粹使用 API 函数来获取和设置实例属性的值,而 **无需采用** KeyValueCoding
协议。
import KeyValueCoding
struct Resolution {
let width: Int
let height: Int
}
var resolution = Resolution(width: 1920, height: 1080)
print(resolution)
// Prints: Resolution(width: 1920, height: 1080)
swift_setValue(3840, to: &resolution, keyPath: \Resolution.width)
swift_setValue(2160, to: &resolution, keyPath: \Resolution.height)
if let width = swift_value(of: &resolution, keyPath: \Resolution.width) as? Int,
let height = swift_value(of: &resolution, keyPath: \Resolution.height) as? Int
{
print("\(width)x\(height)")
// Prints: 3840x2160
}
采用 KeyValueCoding
协议的 struct
或 class
的 Swift 实例对其属性符合键值编码,并且可以通过基本下标 [key]
和 [keyPath]
进行寻址。
返回实例的元数据,其中包括其类型、种类、大小和可访问属性的列表。
import KeyValueCoding
struct Resolution: KeyValueCoding {
let width: Int
let height: Int
}
let resolution = Resolution(width: 1920, height: 1080)
print(resolution.metadata)
打印
Metadata(type: Resolution, kind: .struct, size: 16, properties: [
Property(name: 'width', isStrong: true, isLazy: false, isVar: false, offset: 0),
Property(name: 'height', isStrong: true, isLazy: false, isVar: false, offset: 8)
])
获取并设置由字符串键标识的属性的值。
import KeyValueCoding
struct Resolution: KeyValueCoding {
let width: Int
let height: Int
}
var resolution = Resolution(width: 1920, height: 1080)
resolution["width"] = 2048
if let width: Int = resolution["width"] {
print(width) // Prints: 2048
}
获取并设置由键路径标识的属性的值。
import KeyValueCoding
struct Resolution: KeyValueCoding {
let width: Int
let height: Int
}
var resolution = Resolution(width: 1920, height: 1080)
resolution[\Resolution.width] = 2048
if let width: Int = resolution[\Resolution.width] {
print(width) // Prints: 2048
}
全局 API 函数,用于设置、获取和检索来自任何实例或类型的元数据信息,**即使没有采用** KeyValueCoding
协议。
返回实例或类型的元数据,其中包括其 type
、kind
、size
和可访问的 properties
。
import KeyValueCoding
struct Resolution {
let width: Int
let height: Int
}
let resolution = Resolution(width: 1920, height: 1080)
var metadata = swift_metadata(of: resolution)
// OR
metadata = swift_metadata(of: type(of: resolution))
// OR
metadata = swift_metadata(of: Resolution.self)
print(metadata)
打印
Metadata(type: Resolution, kind: .struct, size: 16, properties: [
Property(name: 'width', isStrong: true, isLazy: false, isVar: false, offset: 0),
Property(name: 'height', isStrong: true, isLazy: false, isVar: false, offset: 8)
])
返回由给定字符串键或键路径标识的实例属性的值。
import KeyValueCoding
struct Resolution {
let width: Int
let height: Int
}
var resolution = Resolution(width: 1920, height: 1080)
if let width = swift_value(of: &resolution, key: "width") as? Int {
print(width) // Prints: 1920
}
// OR
if let width = swift_value(of: &resolution, keyPath: \Resolution.width) as? Int {
print(width) // Prints: 1920
}
将由给定字符串键或键路径指定的实例的属性设置为给定的值。
import KeyValueCoding
struct Resolution {
let width: Int
let height: Int
}
var resolution = Resolution(width: 1920, height: 1080)
swift_setValue(2048, to: &resolution, key: "width")
// OR
swift_setValue(2048, to: &resolution, keyPath: \Resolution.width)
print(resolution) // Prints: Resolution(width: 2048, height: 1080)
Xcode > File > Add Packages...
(Xcode > 文件 > 添加包...)https://github.com/ikhvorost/KeyValueCoding.git
import KeyValueCoding
将 KeyValueCoding
包依赖项添加到您的 Package.swift
文件中
let package = Package(
...
dependencies: [
.package(url: "https://github.com/ikhvorost/KeyValueCoding.git", from: "1.0.0")
],
targets: [
.target(name: "YourPackage",
dependencies: [
.product(name: "KeyValueCoding", package: "KeyValueCoding")
]
),
...
...
)
KeyValueCoding 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。