Skip to content

Instantly share code, notes, and snippets.

@RyadPasha
Created January 4, 2024 19:47
Show Gist options
  • Save RyadPasha/c7bc712ffe4223d8aac50eb8fd680600 to your computer and use it in GitHub Desktop.
Save RyadPasha/c7bc712ffe4223d8aac50eb8fd680600 to your computer and use it in GitHub Desktop.
A utility struct for managing device model mappings based on hardware machine identifiers.
//
// DeviceModelManager.swift
// A utility struct for managing device model mappings based on hardware machine identifiers.
//
// @author Mohamed Riyad <m@ryad.dev>
// @link https://RyadPasha.com
// @license MIT
//
import Foundation
struct DeviceModelManager {
/// A mapping of hardware machine identifiers to corresponding device model names loaded from a JSON file.
static let platformMapping: [String: String] = {
// See: https://gist.github.com/adamawolf/3048717
do {
guard let jsonPath = Bundle.main.path(forResource: "DeviceMapping", ofType: "json"),
let jsonData = try? Data(contentsOf: URL(fileURLWithPath: jsonPath)),
let mapping = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: String]
else {
print("Error: Unable to read or parse DeviceMapping.json")
return [:]
}
return mapping
} catch {
print("Error: \(error)")
return [:]
}
}()
/// A mapping of hardware machine identifiers to corresponding device model names loaded from a text file.
static let platformMappingFromTxtFile: [String: String] = {
guard let filePath = Bundle.main.path(forResource: "DeviceMapping", ofType: "txt") else {
print("File DeviceMapping.txt is not found")
return [:]
}
do {
let fileContent = try String(contentsOfFile: filePath, encoding: .utf8)
let lines = fileContent.components(separatedBy: .newlines)
var mapping: [String: String] = [:]
for line in lines {
let components = line.components(separatedBy: ":")
if components.count == 2 {
let key = components[0].trimmingCharacters(in: .whitespacesAndNewlines)
var value = components[1].trimmingCharacters(in: .whitespacesAndNewlines)
// Replace plus signs with " + " in the value
value = value.replacingOccurrences(of: "+", with: " + ")
// Skip empty rows
if !key.isEmpty && !value.isEmpty {
mapping[key] = value
}
}
}
return mapping
} catch {
print("Error reading file: \(error)")
return [:]
}
}()
/// Retrieves the user's device model based on the hardware machine identifier.
///
/// - Parameters:
/// - fileType: The type of file containing the device model mapping. Default is "txt".
/// - Returns: The device model name mapped from the hardware machine identifier.
static func userDeviceModel(using fileType: String = "txt") -> String {
var size = 0
sysctlbyname("hw.machine", nil, &size, nil, 0)
var machine = [CChar](repeating: 0, count: Int(size))
sysctlbyname("hw.machine", &machine, &size, nil, 0)
let platform = String(cString: machine)
// Choose the mapping function based on the provided fileType
var mappingVariable: [String: String] = [:]
if fileType == "txt" {
mappingVariable = platformMappingFromTxtFile
} else if fileType == "json" {
mappingVariable = platformMapping
} else {
fatalError("Invalid fileType")
}
// Use the selected mapping variable
if let deviceName = mappingVariable[platform] {
return deviceName
}
// If the platform is not found in the mapping, return the original platform value
return platform
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment