用从系统(macOS)收集的数据初始化模型类的正确方法

时间:2019-03-18 15:24:20

标签: swift macos model-view-controller initialization

我需要某些类型的系统信息来配置我的应用。我想通过有一个模型类来实现此目的,以使信息可用。我知道如何获取所需的信息,但是我正努力将收集到的信息存储在模型类的属性中。

我希望能够:

let sysInfoModel = SysInfoModel()

let installedOsVersion = sysInfoModel.osVersion

应从需要设置此信息的vieController实例化模型类。 我认为我的全部尝试都是错误的,以实现这种目标。这样做的正确方法是什么?

class SysInfoModel {

    // Properties
    let macModel: String?
    let osVersion: String?

    // Initialization
    init() {
        if let actualModel = getMacModel() { //ERROR: 'self' used in method call 'getMacModel' before all stored properties are initialized
            self.macModel = actualModel
        } else {
            macModel = "Hardware model not found"
        }

        if let actualOsVersion = getOsVersion() { // ERROR: 'self' used in method call 'getOsVersion' before all stored properties are initialized
            osVersion = actualOsVersion
        } else {
            osVersion = "OS Version not available"
        }
    }


    // Returns the hardware model identifier as a string
    func getMacModel()  -> String? {

        var modelIdentifier: String?

        let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))
        if let modelData = IORegistryEntryCreateCFProperty(service, "model" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? Data {
            modelIdentifier = String(data: modelData, encoding: .utf8)
        }

        IOObjectRelease(service)
        return modelIdentifier
    }

    // Returns the OS Version as a String
    func getOsVersion() -> String? {

        let osVersion: OperatingSystemVersion = ProcessInfo.processInfo.operatingSystemVersion
        let osVersionString = String("\(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)")

        return osVersionString
    }
}

根据马特的回答进行更新:

// Properties
var askSystem: AskTheSystem
let macModel: String?
let osVersion: String?

init() {

    askSystem = AskTheSystem()

    if let actualModel = askSystem.getMacModel() {
        self.macModel = actualModel
    } else {
        macModel = "Hardware model not found"
    }

    if let actualOsVersion = askSystem.getOsVersion() {
        osVersion = actualOsVersion
    } else {
        osVersion = "OS Version not available"
    }
}

我做到了,可以将功能getMacModel()getOsVersion()放在一个单独的类AskTheSystem中。在SysInfoModel中实例化它。 可行,但这是一个好习惯吗?我看不到只为那些功能添加另一个类的意义吗?这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我同意马特,正确是一种判断

一个合理的解决方案是延迟实例化的属性,第一次访问该属性时,一次都会检索这两个值

class SysInfoModel {

    // Returns the hardware model identifier as a string
    lazy var macModel : String = {
        let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))
        defer{IOObjectRelease(service)}
        guard let modelData = IORegistryEntryCreateCFProperty(service, "model" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? Data else {
            return "Hardware model not found"
        }
        return String(data: modelData, encoding: .utf8)!
    }()

    // Returns the OS Version as a String
    lazy var osVersion : String = {
        let osVersion = ProcessInfo.processInfo.operatingSystemVersion
        return "\(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)"
    }()

}