一个用于读取(和写入)sysctl
值的 Swift 接口。
将以下依赖项添加到您的 Package.swift
文件中
.package(url: "https://github.com/sersoft-gmbh/swift-sysctl.git", from: "1.0.0"),
或通过 Xcode 添加(适用于 Xcode 11 及更高版本)。
使用 Swift Sysctl 非常简单。您只需创建一个 SystemControl
实例并开始访问值。就这么简单
let sysctl = SystemControl()
let machine = sysctl.hardware.machine // String with the value of `hw.machine`.
Swift Sysctl 包含一些常用值,并且会随着时间推移而增长。如果您发现您需要的值尚未存在,您可以轻松添加它们。只需阅读以下章节
您可能知道,sysctl
使用带有点的名称来寻址值。Swift Sysctl 将这些点之间的部分称为“命名空间”,并在 Swift struct
中表示它们。例如,有一个 Hardware
代表 sysctl
中的 hw
命名空间。每个命名空间都有一个父命名空间。如果命名空间位于根目录,请使用 SysctlRootNamespace
作为父命名空间。
当实现您自己的命名空间时,只需使其遵循 SysctlNamespace
协议,定义父命名空间并实现 static var namePart: String { /*...*/ }
,返回您的命名空间的名称部分(例如 Hardware
的 hw
)。
这是一个新的(假想的)命名空间的示例,它也有一个子命名空间
struct Superpower: SysctlNamespace {
typealias ParentNamespace = SysctlRootNamespace
static var namePart: String { "spwr" }
struct Control: SysctlNamespace {
typealias ParentNamespace = Superpower
static var namePart: String { "ctrl" }
}
var control: Control { .init() }
}
extension SysctlRootNamespace {
var superpower: Superpower { .init() }
}
要从 sysctl
访问值,命名空间上有一些(计算)属性。例如,对于 hw.machine
,Hardware
命名空间上有一个属性 machine
。要访问新值,只需在字段所在的命名空间上声明一个新的(计算)属性(在您自己实现的命名空间中或通过扩展现有的命名空间)。这些属性的值类型需要是 Field<T>
,其中 T
是值的类型。Field
是命名空间内 SysctlField
的类型别名。字段包含值的名称的最后一部分。因此,您只需将名称作为字符串返回。如果该值是可写的,您还需要提供一个 nonmutating set
实现,该实现可以留空。
继续我们的示例,以下是 Superpower
上的字段的外观
extension Superpower {
// The current magic level. Read-only.
// The full name will be `spwr.curmaglvl`.
var currentMagicLevel: Field<CInt> { "curmaglvl" }
}
extension Superpower.Control {
// Whether superpowers are enabled. This is writable.
// The full name will be `spwr.ctrl.enabled`.
var isEnabled: Field<Bool> {
get { "enabled" }
nonmutating set {}
}
}
为了让 Swift Sysctl 知道如何读取(或写入)sysctl
中的值,它需要遵循 SysctlValue
协议。但是,sysctl
仅支持非常少的值类型,因此您不太可能需要使另一种类型遵循它。
更可能的情况(但仍然不太可能)是您想要拥有一个自定义类型,该类型由已遵循 SysctlValue
的值表示。在这种情况下,您的类型需要遵循 SysctlValueRepresentable
协议。它的行为与 Swift 的 RawRepresentable
协议非常相似。您需要声明您的类型将使用的底层 SysctlValue
类型,并实现只读属性 var syctlValue: SysctlValue { get }
,您在其中返回您的类型的底层 SysctlValue
。然后您需要在您的类型上实现 init(sysctlValue:)
。Swift Sysctl 会将底层 SysctlValue
传递给此初始化器,您可以从中初始化您的类型。满足这些要求后,Swift Sysctl 将为您提供 SysctlValue
的实现,您可以从/向 sysctl
读取和写入您的类型。
再次继续我们的示例,以下是如何从 sysctl
读取新类型
enum MagicSpellPower: SysctlValueRepresentable {
typealias SysctlValue = CInt
case low(Int)
case medium
case high(unbeatable: Bool)
var sysctlValue: SysctlValue {
switch self {
case .low(let val): return numericCast(val)
case .medium: return 5
case .high(let unbeatable): return unbeatable ? -1 : 10
}
}
init(sysctlValue: SysctlValue) {
switch sysctlValue {
case 0..<5: self = .low(numericCast(sysctlValue))
case 5: self = .medium
case 10: self = .high(unbeatable: false)
case -1: self = .high(unbeatable: true)
default: fatalError("Invalid value: \(sysctlValue)")
}
}
}
虽然尚未集成,但以下功能可能会提供附加价值,并可能在未来加入此软件包
sysctl
失败,Swift Sysctl 会崩溃。API 使用 header doc 进行文档化。如果您喜欢以网页形式查看文档,可以访问在线版本。
如果您发现错误/希望看到新功能,有几种方法可以提供帮助
请参阅 LICENSE 文件。