Swift Sysctl

GitHub release Tests Codacy Badge codecov Docs

一个用于读取(和写入)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 包含一些常用值,并且会随着时间推移而增长。如果您发现您需要的值尚未存在,您可以轻松添加它们。只需阅读以下章节

SysctlNamespace

您可能知道,sysctl 使用带有点的名称来寻址值。Swift Sysctl 将这些点之间的部分称为“命名空间”,并在 Swift struct 中表示它们。例如,有一个 Hardware 代表 sysctl 中的 hw 命名空间。每个命名空间都有一个父命名空间。如果命名空间位于根目录,请使用 SysctlRootNamespace 作为父命名空间。

当实现您自己的命名空间时,只需使其遵循 SysctlNamespace 协议,定义父命名空间并实现 static var namePart: String { /*...*/ },返回您的命名空间的名称部分(例如 Hardwarehw)。

这是一个新的(假想的)命名空间的示例,它也有一个子命名空间

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() }
}

SysctlNamespace.Field

要从 sysctl 访问值,命名空间上有一些(计算)属性。例如,对于 hw.machineHardware 命名空间上有一个属性 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 {}
    }
}

SysctlValueSysctlValueRepresentable

为了让 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)")
        }
    }
}

可能的功能

虽然尚未集成,但以下功能可能会提供附加价值,并可能在未来加入此软件包

文档

API 使用 header doc 进行文档化。如果您喜欢以网页形式查看文档,可以访问在线版本

贡献

如果您发现错误/希望看到新功能,有几种方法可以提供帮助

许可证

请参阅 LICENSE 文件。