├── .gitignore
├── devicehardware_icon.png
├── Tests
├── LinuxMain.swift
└── DeviceHardwareTests
│ ├── XCTestManifests.swift
│ └── DeviceHardwareTests.swift
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── .github
└── workflows
│ └── release.yml
├── LICENSE
├── Package.swift
├── Sources
└── DeviceHardware
│ ├── DeviceHardware.swift
│ ├── MacDeviceHardware.swift
│ └── UIDeviceHardware.swift
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/devicehardware_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Shakshi3104/DeviceHardware/HEAD/devicehardware_icon.png
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import DeviceHardwareTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += DeviceHardwareTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/DeviceHardwareTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(DeviceHardwareTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release Package
2 |
3 | on:
4 | push:
5 | tags:
6 | - "*.*.*"
7 |
8 | jobs:
9 | build:
10 | name: Create Release
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout code
14 | uses: actions/checkout@v3
15 | - name: Set Version
16 | id: version
17 | run: |
18 | VERSION=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
19 | echo "version=$VERSION" >> $GITHUB_OUTPUT
20 | - name: Create Release
21 | id: create_release
22 | uses: softprops/action-gh-release@v1
23 | env:
24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
25 | with:
26 | tag_name: ${{ github.ref }}
27 | name: v${{ steps.version.outputs.VERSION }}
28 | generate_release_notes: true
29 | draft: false
30 | prerelease: false
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Shakshi3104
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "DeviceHardware",
8 | platforms: [
9 | .iOS(.v12),
10 | .macOS(.v10_15)
11 | ],
12 | products: [
13 | // Products define the executables and libraries a package produces, and make them visible to other packages.
14 | .library(
15 | name: "DeviceHardware",
16 | targets: ["DeviceHardware"]),
17 | ],
18 | dependencies: [
19 | // Dependencies declare other packages that this package depends on.
20 | // .package(url: /* package url */, from: "1.0.0"),
21 | ],
22 | targets: [
23 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
24 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
25 | .target(
26 | name: "DeviceHardware",
27 | dependencies: []),
28 | .testTarget(
29 | name: "DeviceHardwareTests",
30 | dependencies: ["DeviceHardware"]),
31 | ]
32 | )
33 |
--------------------------------------------------------------------------------
/Tests/DeviceHardwareTests/DeviceHardwareTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DeviceHardware
3 |
4 | final class DeviceHardwareTests: XCTestCase {
5 |
6 | func testModelIdentifier() {
7 | XCTAssertEqual(MacDeviceHardware.deviceHardware.modelIdentifier, "Mac14,12")
8 | XCTAssertEqual(UIDeviceHardware.deviceHardware.modelIdentifier, "arm64")
9 | }
10 |
11 | func testModelName() {
12 | XCTAssertEqual(MacDeviceHardware.deviceHardware.modelName, "Mac mini (2023)")
13 | }
14 |
15 | func testProcessorName() {
16 | XCTAssertEqual(MacDeviceHardware.deviceHardware.processorName, "Apple M2 Pro")
17 | }
18 |
19 | func testCpu() {
20 | XCTAssertEqual(MacDeviceHardware.deviceHardware.cpu, "3.49GHz 12-core")
21 | }
22 |
23 | func testGpu() {
24 | XCTAssertEqual(MacDeviceHardware.deviceHardware.gpu, "Apple M2 Pro")
25 | }
26 |
27 | func testNeuralEngine() {
28 | XCTAssertEqual(MacDeviceHardware.deviceHardware.neuralEngine, "16-core")
29 | }
30 |
31 | func testProcessorCount() {
32 | XCTAssertEqual(MacDeviceHardware.deviceHardware.processorCount, 12)
33 | }
34 |
35 | func testRamString() {
36 | XCTAssertEqual(MacDeviceHardware.deviceHardware.ramString, "32GB")
37 | }
38 |
39 | func testUINeuralEngine() {
40 | XCTAssertEqual(UIDeviceHardware.deviceHardware.neuralEngine, "N/A")
41 | }
42 |
43 | func testCallPerformance() {
44 | self.measure {
45 | for _ in 0..<10000 {
46 | _ = MacDeviceHardware.deviceHardware.modelName
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Sources/DeviceHardware/DeviceHardware.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Metal
3 |
4 |
5 | protocol DeviceHardware {
6 | /// model name, such as iPhone 8
7 | var modelName: String { get }
8 | /// processor name, such as A11 Bionic
9 | var processorName: String { get }
10 | /// CPU information, such as 2.39GHz 6-core
11 | var cpu: String { get }
12 | /// GPU information, such as Apple A11 GPU
13 | var gpu: String { get }
14 | /// Neural Engine, such as 2-core
15 | var neuralEngine: String { get }
16 |
17 | /// Model Identifier, such as iPhone10,1
18 | var modelIdentifier: String { get }
19 | /// number of processor, such as 6
20 | var processorCount: Int { get }
21 | /// physical memory size [B], such as 2071019520
22 | var ram: Int { get }
23 | /// physical memory size, such as 2GB
24 | var ramString: String { get }
25 | }
26 |
27 | extension DeviceHardware {
28 | func getMetalGpu() -> String {
29 | if #available(OSX 10.11, iOS 8.0, macCatalyst 13.0, *) {
30 | guard let device = MTLCreateSystemDefaultDevice() else {
31 | return "Unknown"
32 | }
33 |
34 | let deviceName = device.name
35 | .replacingOccurrences(of: "(R)", with: "")
36 | .replacingOccurrences(of: "(TM)", with: "")
37 | return deviceName
38 | } else {
39 | // Fallback on earlier versions
40 | // Not support Metal
41 | return "Not support Metal"
42 | }
43 | }
44 |
45 | func getRAM() -> Int {
46 | return Int(ProcessInfo.processInfo.physicalMemory)
47 | }
48 |
49 | func getRAMString() -> String {
50 | let bytes = getRAM()
51 | let formatter = ByteCountFormatter()
52 | formatter.countStyle = .memory
53 | return formatter.string(fromByteCount: Int64(bytes)).replacingOccurrences(of: " ", with: "")
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DeviceHardware
2 |
3 |
4 |

5 |
6 |
7 | DeviceHardware is a package for getting iPhone, iPad and Mac model names and hardware information, such as SoC name.
8 |
9 | Support for iOS devices and Macs by October 23, 2025 (JST).
10 |
11 | ## Usage
12 |
13 | ```swift
14 | import DeviceHardware
15 | ```
16 | ### iOS
17 |
18 | At first
19 |
20 | ```swift
21 | let device = UIDeviceHardware.deviceHardware
22 | ```
23 |
24 | Eample on iPhone 8 running iOS 14.2
25 |
26 | ```swift
27 | device.modelName // iPhone 8
28 | device.processorName // Apple A11 Bionic
29 | device.cpu // 2.39GHz 6-core
30 | device.gpu // Apple A11 GPU
31 | device.neuralEngine // 2-core
32 | device.modelIdentifier // iPhone10,1
33 | device.processorCount // 6
34 | device.ram // 2071019520
35 | device.ramString // 1.93GB
36 | ```
37 |
38 | ### macOS
39 |
40 | At first
41 |
42 | ```swift
43 | let device = MacDeviceHardware.deviceHardware
44 | ```
45 |
46 | Eample on MacBook Pro (13-inch, 2018, Four Thunderbolt 3 ports) running macOS 11.0.1
47 |
48 | ```swift
49 | device.modelName // MacBook Pro (13-inch, 2018, Four Thunderbolt 3 ports)
50 | device.processorName // Intel Core i5-8259U
51 | device.cpu // 2.30GHz 4-core
52 | device.gpu // Intel Iris Plus Graphics 655
53 | device.neuralEngine // None
54 | device.modelIdentifier // MacBookPro15,2
55 | device.processorCount // 8
56 | device.ram // 17179869184
57 | device.ramString // 16GB
58 | ```
59 |
60 | Eample on MacBook Pro (13-inch, M1, 2020) running macOS 11.2.3
61 |
62 | ```swift
63 | device.modelName // MacBook Pro (13-inch, M1, 2020)
64 | device.processorName // Apple M1
65 | device.cpu // 3.2GHz 8-core
66 | device.gpu // Apple M1
67 | device.neuralEngine // 16-core
68 | device.modelIdentifier // MacBookPro17,1
69 | device.processorCount // 8
70 | device.ram // 17179869184
71 | device.ramString // 16GB
72 | ```
73 |
74 | ### Mac models that cannot get the correct model name
75 |
76 | You may not get the correct model name on some Macs. In the following models, you may not get the correct model name if the Mac have been customized to Intel Core i7.
77 |
78 | - MacBook Air (13-inch, 2017)
79 | - MacBook Air (13-inch, Early 2015)
80 | - MacBook Air (13-inch, Early 2014)
81 | - MacBook Air (13-inch, Mid 2013)
82 | - MacBook Air (11-inch, Early 2014)
83 | - MacBook Air (11-inch, Mid 2013)
84 |
85 | ## Requirements
86 |
87 | This package is compatible with iOS 8 or higher and macOS 10.15 or higher. However, Mac device information can only be got for models that support macOS 11.
88 |
89 | ## Installation
90 |
91 | ### Swift Package Manager
92 | Add this Swift package in Xcode using its GitHub repository URL. (File > Swift Packages > Add Package Dependency...)
93 |
94 | ## License
95 | DeviceHardware is available under the MIT license. See the LICENSE file for more info.
96 |
--------------------------------------------------------------------------------
/Sources/DeviceHardware/MacDeviceHardware.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public class MacDeviceHardware: DeviceHardware {
4 | public static let deviceHardware = MacDeviceHardware()
5 |
6 | /// model name, such as MacBook Air (Retina, 13-inch, 2020)
7 | public var modelName: String {
8 | let modelName_ = getModelName() ?? "Unknown"
9 | return modelName_
10 | }
11 | /// processor name, such as Intel Core i5-5250U
12 | public var processorName: String {
13 | let processorName_ = getProcessorName() ?? "Unknown"
14 | return processorName_
15 | }
16 | /// CPU information, such as 1.60GHz 2-core
17 | public var cpu: String {
18 | let cpu_ = getCpu() ?? "Unknown"
19 | return cpu_
20 | }
21 | /// GPU information, such as Intel Iris Plus Graphics 655
22 | public var gpu: String {
23 | return getMetalGpu()
24 | }
25 | /// Neural Engine, such as 16-core or None
26 | public var neuralEngine: String {
27 | let neuralEngine_ = getNeuralEngine() ?? "Unknown"
28 | return neuralEngine_
29 | }
30 |
31 | /// Model Identifier, such as MacBookAir9,1
32 | public var modelIdentifier: String {
33 | let modelId = getModelIdentifier() ?? "Unknown"
34 | return modelId
35 | }
36 | /// number of (logical) processor, such as 4
37 | public var processorCount: Int {
38 | return ProcessInfo.processInfo.processorCount
39 | }
40 | /// physical memory size [B], such as 8589934592
41 | public var ram: Int {
42 | return getRAM()
43 | }
44 | /// physical memory size, such as 8GB
45 | public var ramString: String {
46 | return getRAMString()
47 | }
48 |
49 | // MARK: - Model Identifier
50 | enum ModelIdentifier: String {
51 | // MARK: MacBook Air
52 | /// MacBook Air (13-inch, M4, 2025)
53 | case Mac16_12 = "Mac16,12"
54 | /// MacBook Air (15-inch, M4, 2025)
55 | case Mac16_13 = "Mac16,13"
56 | /// MacBook Air (13-inch, M3, 2024)
57 | case Mac15_12 = "Mac15,12"
58 | /// MacBook Air (15-inch, M3, 2024)
59 | case Mac15_13 = "Mac15,13"
60 | /// MacBook Air (15-inch, M2, 2023)
61 | case Mac14_15 = "Mac14,15"
62 | /// MacBook Air (M2, 2022)
63 | case Mac14_2 = "Mac14,2"
64 | /// MacBook Air (M1, 2020)
65 | case MacBookAir10_1 = "MacBookAir10,1"
66 | /// MacBook Air (Retina, 13-inch, 2020)
67 | case MacBookAir9_1 = "MacBookAir9,1"
68 | /// MacBook Air (Retina, 13-inch, 2019)
69 | case MacBookAir8_2 = "MacBookAir8,2"
70 | /// MacBook Air (Retina, 13-inch, 2018)
71 | case MacBookAir8_1 = "MacBookAir8,1"
72 | /// MacBook Air (13-inch, 2017), MacBook Air (13-inch, Early 2015)
73 | case MacBookAir7_2 = "MacBookAir7,2"
74 | /// MacBook Air (11-inch, Early 2015)
75 | case MacBookAir7_1 = "MacBookAir7,1"
76 | /// MacBook Air (13-inch, Early 2014), MacBook Air (13-inch, Mid 2013)
77 | case MacBookAir6_2 = "MacBookAir6,2"
78 | /// MacBook Air (11-inch, Early 2014), MacBook Air (11-inch, Mid 2013)
79 | case MacBookAir6_1 = "MacBookAir6,1"
80 |
81 | // MARK: MacBook Pro
82 | /// MacBook Pro (M5, 2025) // 2025年10月発売モデル
83 | case Mac17_2 = "Mac17,2"
84 | /// MacBook Pro (14-inch, 2024) / M4
85 | case Mac16_1 = "Mac16,1"
86 | /// MacBook Pro (14-inch, 2024) / M4 Pro or M4 Max
87 | case Mac16_6 = "Mac16,6"
88 | case Mac16_8 = "Mac16,8"
89 | /// MacBook Pro (16-inch, 2024) / M4 Pro or M4 Max
90 | case Mac16_5 = "Mac16,5"
91 | case Mac16_7 = "Mac16,7"
92 | /// MacBook Pro (14-inch, Nov 2023) / M3
93 | case Mac15_3 = "Mac15,3"
94 | /// MacBook Pro (14-inch, Nov 2023) / M3 Pro or M3 Max
95 | case Mac15_6 = "Mac15,6"
96 | case Mac15_8 = "Mac15,8"
97 | case Mac15_10 = "Mac15,10"
98 | /// MacBook Pro (16-inch, Nov 2023) / M3 Pro or M3 Max
99 | case Mac15_7 = "Mac15,7"
100 | case Mac15_9 = "Mac15,9"
101 | case Mac15_11 = "Mac15,11"
102 | /// MacBook Pro (14-inch, 2023) / M2 Pro
103 | case Mac14_9 = "Mac14,9"
104 | /// MacBook Pro (14-inch, 2023) / M2 Max
105 | case Mac14_5 = "Mac14,5"
106 | /// MacBook Pro (16-inch, 2023) / M2 Pro
107 | case Mac14_10 = "Mac14,10"
108 | /// MacBook Pro (16-inch, 2023) / M2 Max
109 | case Mac14_6 = "Mac14,6"
110 | /// MacBook Pro (13-inch, M2, 2022)
111 | case Mac14_7 = "Mac14,7"
112 | /// MacBook Pro (16-inch, 2021) / M1 Pro
113 | case MacBookPro18_1 = "MacBookPro18,1"
114 | /// MacBook Pro (16-inch, 2021) / M1 Max
115 | case MacBookPro18_2 = "MacBookPro18,2"
116 | /// MacBook Pro (14-inch, 2021) / M1 Pro
117 | case MacBookPro18_3 = "MacBookPro18,3"
118 | /// MacBook Pro (14-inch, 2021) / M1 Max
119 | case MacBookPro18_4 = "MacBookPro18,4"
120 | /// MacBook Pro (13-inch, M1, 2020)
121 | case MacBookPro17_1 = "MacBookPro17,1"
122 | /// MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
123 | case MacBookPro16_3 = "MacBookPro16,3"
124 | /// MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
125 | case MacBookPro16_2 = "MacBookPro16,2"
126 | /// MacBook Pro (16-inch, 2019)
127 | case MacBookPro16_4 = "MacBookPro16,4"
128 | case MacBookPro16_1 = "MacBookPro16,1"
129 | /// MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports
130 | case MacBookPro15_4 = "MacBookPro15,4"
131 | /// MacBook Pro (15-inch, 2019)
132 | case MacBookPro15_3 = "MacBookPro15,3"
133 | /// MacBook Pro (15-inch, 2019), MacBook Pro (15-inch, 2018)
134 | case MacBookPro15_1 = "MacBookPro15,1"
135 | /// MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports), MacBook Pro (13-inch, 2018, Four Thunderbolt 3 ports)
136 | case MacBookPro15_2 = "MacBookPro15,2"
137 | /// MacBook Pro (15-inch, 2017)
138 | case MacBookPro14_3 = "MacBookPro14,3"
139 | /// MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)
140 | case MacBookPro14_2 = "MacBookPro14,2"
141 | /// MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
142 | case MacBookPro14_1 = "MacBookPro14,1"
143 | /// MacBook Pro (15-inch, 2016)
144 | case MacBookPro13_3 = "MacBookPro13,3"
145 | /// MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)
146 | case MacBookPro13_2 = "MacBookPro13,2"
147 | /// MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)
148 | case MacBookPro13_1 = "MacBookPro13,1"
149 | /// MacBook Pro (Retina, 15-inch, Mid 2015)
150 | case MacBookPro11_5 = "MacBookPro11,5"
151 | case MacBookPro11_4 = "MacBookPro11,4"
152 | /// MacBook Pro (Retina, 13-inch, Early 2015)
153 | case MacBookPro12_1 = "MacBookPro12,1"
154 | /// MacBook Pro (Retina, 15-inch, Mid 2014), MacBook Pro (Retina, 15-inch, Late 2013)
155 | case MacBookPro11_3 = "MacBookPro11,3"
156 | case MacBookPro11_2 = "MacBookPro11,2"
157 | /// MacBook Pro (Retina, 13-inch, Mid 2014), MacBook Pro (Retina, 13-inch, Late 2013)
158 | case MacBookPro11_1 = "MacBookPro11,1"
159 |
160 | // MARK: MacBook (12-inch)
161 | /// MacBook (Retina, 12-inch, 2017)
162 | case MacBook10_1 = "MacBook10,1"
163 | /// MacBook (Retina, 12-inch, Early 2016)
164 | case MacBook9_1 = "MacBook9,1"
165 | /// MacBook (Retina, 12-inch, Early 2015)
166 | case MacBook8_1 = "MacBook8,1"
167 |
168 | // MARK: Mac Pro
169 | /// Mac Pro (2023)
170 | case Mac14_8 = "Mac14,8"
171 | /// Mac Pro (2019)
172 | case MacPro7_1 = "MacPro7,1"
173 | /// Mac Pro (Late 2013)
174 | case MacPro6_1 = "MacPro6,1"
175 |
176 | // MARK: Mac mini
177 | /// Mac mini (2024) / M4
178 | case Mac16_10 = "Mac16,10"
179 | /// Mac mini (2024) / M4 Pro
180 | case Mac16_15 = "Mac16,15"
181 | /// Mac mini (2023) / M2
182 | case Mac14_3 = "Mac14,3"
183 | /// Mac mini (2023) / M2 Pro
184 | case Mac14_12 = "Mac14,12"
185 | /// Mac mini (M1, 2020)
186 | case Macmini9_1 = "Macmini9,1"
187 | /// Mac mini (2018)
188 | case Macmini8_1 = "Macmini8,1"
189 | /// Mac mini (Late 2014)
190 | case Macmini7_1 = "Macmini7,1"
191 |
192 | // MARK: iMac Pro
193 | /// iMac Pro
194 | case iMacPro1_1 = "iMacPro1,1"
195 |
196 | // MARK: iMac
197 | /// iMac (24-inch, 2024, Two ports)
198 | case Mac16_2 = "Mac16,2"
199 | /// iMac (24-inch, 2024, Four ports)
200 | case Mac16_3 = "Mac16,3"
201 | /// iMac (24-inch, 2023, Two ports)
202 | case Mac15_4 = "Mac15,4"
203 | /// iMac (24-inch, 2023, Four ports)
204 | case Mac15_5 = "Mac15,5"
205 | /// iMac (24-inch, M1, 2021)
206 | case iMac21_1 = "iMac21,1"
207 | case iMac21_2 = "iMac21,2"
208 | /// iMac (Retina 5K, 27-inch, 2020)
209 | case iMac20_2 = "iMac20,2"
210 | case iMac20_1 = "iMac20,1"
211 | /// iMac (Retina 5K, 27-inch, 2019)
212 | case iMac19_1 = "iMac19,1"
213 | /// iMac (Retina 4K, 21.5-inch, 2019)
214 | case iMac19_2 = "iMac19,2"
215 | /// iMac (Retina 5K, 27-inch, 2017)
216 | case iMac18_3 = "iMac18,3"
217 | /// iMac (Retina 4K, 21.5-inch, 2017)
218 | case iMac18_2 = "iMac18,2"
219 | /// iMac (21.5-inch, 2017)
220 | case iMac18_1 = "iMac18,1"
221 | /// iMac (Retina 5K, 27-inch, Late 2015)
222 | case iMac17_1 = "iMac17,1"
223 | /// iMac (Retina 4K, 21.5-inch, Late 2015)
224 | case iMac16_2 = "iMac16,2"
225 | /// iMac (21.5-inch, Late 2015)
226 | case iMac16_1 = "iMac16,1"
227 | /// iMac (Retina 5K, 27-inch, Mid 2015), iMac (Retina 5K, 27-inch, Late 2014)
228 | case iMac15_1 = "iMac15,1"
229 | /// iMac (21.5-inch, Mid 2014)
230 | case iMac14_4 = "iMac14,4"
231 | /// iMac (27-inch, Late 2013)
232 | case iMac14_2 = "iMac14,2"
233 | /// iMac (21.5-inch, Late 2013)
234 | case iMac14_1 = "iMac14,1"
235 | /// iMac (27-inch, Late 2012)
236 | case iMac13_2 = "iMac13,2"
237 | /// iMac (21.5-inch, Late 2012)
238 | case iMac13_1 = "iMac13,1"
239 |
240 | // MARK: Mac Studio
241 | /// Mac Studio (2023) / M2 Max
242 | case Mac14_13 = "Mac14,13"
243 | /// Mac Studio (2023) / M2 Ultra
244 | case Mac14_14 = "Mac14,14"
245 | /// Mac Studio (2022) / M1 Max
246 | case Mac13_1 = "Mac13,1"
247 | /// Mac Studio (2022) / M1 Ultra
248 | case Mac13_2 = "Mac13,2"
249 |
250 | // TODO: Add core counts of Neural Engine when new Apple Silicon Series is announced.
251 | // Neural Engine Information
252 | func neuralEngine() -> String {
253 | switch self {
254 | /// M1
255 | case .MacBookAir10_1, .MacBookPro17_1, .Macmini9_1, .iMac21_1, .iMac21_2:
256 | return "16-core"
257 | /// M1 Pro
258 | case .MacBookPro18_1, .MacBookPro18_3:
259 | return "16-core"
260 | /// M1 Max
261 | case .MacBookPro18_2, .MacBookPro18_4, .Mac13_1:
262 | return "16-core"
263 | /// M1 Ultra
264 | case .Mac13_2:
265 | return "32-core"
266 | /// M2
267 | case .Mac14_2, .Mac14_7, .Mac14_15:
268 | return "16-core"
269 | /// M2 Pro
270 | case .Mac14_9, .Mac14_10, .Mac14_12:
271 | return "16-core"
272 | /// M2 Max
273 | case .Mac14_5, .Mac14_6, .Mac14_13:
274 | return "16-core"
275 | /// M2 Ultra
276 | case .Mac14_14, .Mac14_8:
277 | return "32-core"
278 | /// M3, M3 Pro, M3 Max
279 | case .Mac15_3, .Mac15_4, .Mac15_5, .Mac15_6, .Mac15_7, .Mac15_8, .Mac15_9, .Mac15_10, .Mac15_11, .Mac15_12, .Mac15_13:
280 | return "16-core"
281 | /// M4, M4 Pro, M4 Max
282 | case .Mac16_1, .Mac16_2, .Mac16_3, .Mac16_5, .Mac16_6, .Mac16_7, .Mac16_8, .Mac16_10, .Mac16_15, .Mac16_12, .Mac16_13:
283 | return "16-core"
284 | /// M5
285 | case .Mac17_2:
286 | return "16-core"
287 | default:
288 | return "None"
289 | }
290 | }
291 |
292 | // model name
293 | func modelName() -> String {
294 | switch self {
295 | // MARK: MacBook Air
296 | case .Mac16_12:
297 | return "MacBook Air (13-inch, M4, 2025)"
298 | case .Mac16_13:
299 | return "MacBook Air (15-inch, M4, 2025)"
300 | case .Mac15_12:
301 | return "MacBook Air (13-inch, M3, 2024)"
302 | case .Mac15_13:
303 | return "MacBook Air (15-inch, M3, 2024)"
304 | case .Mac14_15:
305 | return "MacBook Air (15-inch, M2, 2023)"
306 | case .Mac14_2:
307 | return "MacBook Air (M2, 2022)"
308 | case .MacBookAir10_1:
309 | return "MacBook Air (M1, 2020)"
310 | case .MacBookAir9_1:
311 | return "MacBook Air (Retina, 13-inch, 2020)"
312 | case .MacBookAir8_2:
313 | return "MacBook Air (Retina, 13-inch, 2019)"
314 | case .MacBookAir8_1:
315 | return "MacBook Air (Retina, 13-inch, 2018)"
316 | case .MacBookAir7_2:
317 | /// Need some decision processing
318 | return "MacBook Air (13-inch, 2017) / (13-inch, Early 2015)"
319 | case .MacBookAir7_1:
320 | return "MacBook Air (11-inch, Early 2015)"
321 | case .MacBookAir6_2:
322 | /// Need some decision processing
323 | return "MacBook Air (13-inch, Early 2014) / (13-inch, Mid 2013)"
324 | case .MacBookAir6_1:
325 | /// Need some decision processing
326 | return "MacBook Air (11-inch, Early 2014) / (11-inch, Mid 2013)"
327 |
328 | // MARK: MacBook Pro
329 | case .Mac17_2:
330 | return "MacBook Pro (14-inch, 2025)"
331 | case .Mac16_1, .Mac16_6, .Mac16_8:
332 | return "MacBook Pro (14-inch, 2024)"
333 | case .Mac16_7, .Mac16_5:
334 | return "MacBook Pro (16-inch, 2024)"
335 | case .Mac15_3, .Mac15_6, .Mac15_8, .Mac15_10:
336 | return "MacBook Pro (14-inch, Nov 2023)"
337 | case .Mac15_7, .Mac15_9, .Mac15_11:
338 | return "MacBook Pro (16-inch, Nov 2023)"
339 | case .Mac14_5, .Mac14_9:
340 | return "MacBook Pro (14-inch, 2023)"
341 | case .Mac14_6, .Mac14_10:
342 | return "MacBook Pro (16-inch, 2023)"
343 | case .Mac14_7:
344 | return "MacBook Pro (13-inch, M2, 2022)"
345 | case .MacBookPro18_1, .MacBookPro18_2:
346 | return "MacBook Pro (16-inch, 2021)"
347 | case .MacBookPro18_3, .MacBookPro18_4:
348 | return "MacBook Pro (14-inch, 2021)"
349 | case .MacBookPro17_1:
350 | return "MacBook Pro (13-inch, M1, 2020)"
351 | case .MacBookPro16_3:
352 | return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)"
353 | case .MacBookPro16_2:
354 | return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)"
355 | case .MacBookPro16_1, .MacBookPro16_4:
356 | return "MacBook Pro (16-inch, 2019)"
357 | case .MacBookPro15_4:
358 | return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)"
359 | case .MacBookPro15_3:
360 | return "MacBook Pro (15-inch, 2019)"
361 | case .MacBookPro15_1:
362 | /// Need some decision processing
363 | return "MacBook Pro (15-inch, 2019) / (15-inch, 2018)"
364 | case .MacBookPro15_2:
365 | /// Need some decision processing
366 | return "MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports) / (13-inch, 2018, Four Thunderbolt 3 ports)"
367 | case .MacBookPro14_3:
368 | return "MacBook Pro (15-inch, 2017)"
369 | case .MacBookPro14_2:
370 | return "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)"
371 | case .MacBookPro14_1:
372 | return "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)"
373 | case .MacBookPro13_3:
374 | return "MacBook Pro (15-inch, 2016)"
375 | case .MacBookPro13_2:
376 | return "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)"
377 | case .MacBookPro13_1:
378 | return "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)"
379 | case .MacBookPro11_5, .MacBookPro11_4:
380 | return "MacBook Pro (Retina, 15-inch, Mid 2015)"
381 | case .MacBookPro12_1:
382 | return "MacBook Pro (Retina, 13-inch, Early 2015)"
383 | case .MacBookPro11_3, .MacBookPro11_2:
384 | /// Need some decision processing
385 | return "MacBook Pro (Retina, 15-inch, Mid 2014) / (Retina, 15-inch, Late 2013)"
386 | case .MacBookPro11_1:
387 | /// Need some decision processing
388 | return "MacBook Pro (Retina, 13-inch, Mid 2014) / (Retina, 13-inch, Late 2013)"
389 |
390 | // MARK: MacBook (12-inch)
391 | case .MacBook10_1:
392 | return "MacBook (Retina, 12-inch, 2017)"
393 | case .MacBook9_1:
394 | return "MacBook (Retina, 12-inch, Early 2016)"
395 | case .MacBook8_1:
396 | return "MacBook (Retina, 12-inch, Early 2015)"
397 |
398 | // MARK: Mac Pro
399 | case .Mac14_8:
400 | return "Mac Pro (2023)"
401 | case .MacPro7_1:
402 | return "Mac Pro (2019)"
403 | case .MacPro6_1:
404 | return "Mac Pro (Late 2013)"
405 |
406 | // MARK: Mac mini
407 | case .Mac16_15, .Mac16_10:
408 | return "Mac mini (2024)"
409 | case .Mac14_3, .Mac14_12:
410 | return "Mac mini (2023)"
411 | case .Macmini9_1:
412 | return "Mac mini (M1, 2020)"
413 | case .Macmini8_1:
414 | return "Mac mini (2018)"
415 | case .Macmini7_1:
416 | return "Mac mini (Late 2014)"
417 |
418 | // MARK: iMac Pro
419 | case .iMacPro1_1:
420 | return "iMac Pro (2017)"
421 |
422 | // MARK: iMac
423 | case .Mac16_2:
424 | return "iMac (24-inch, 2024, Two ports)"
425 | case .Mac16_3:
426 | return "iMac (24-inch, 2024, Four ports)"
427 | case .Mac15_5:
428 | return "iMac (24-inch, 2023, Four ports)"
429 | case .Mac15_4:
430 | return "iMac (24-inch, 2023, Two ports)"
431 | case .iMac21_1, .iMac21_2:
432 | return "iMac (24-inch, M1, 2021)"
433 | case .iMac20_2, .iMac20_1:
434 | return "iMac (Retina 5K, 27-inch, 2020)"
435 | case .iMac19_1:
436 | return "iMac (Retina 5K, 27-inch, 2019)"
437 | case .iMac19_2:
438 | return "iMac (Retina 4K, 21.5-inch, 2019)"
439 | case .iMac18_3:
440 | return "iMac (Retina 5K, 27-inch, 2017)"
441 | case .iMac18_2:
442 | return "iMac (Retina 4K, 21.5-inch, 2017)"
443 | case .iMac18_1:
444 | return "iMac (21.5-inch, 2017)"
445 | case .iMac17_1:
446 | return "iMac (Retina 5K, 27-inch, Late 2015)"
447 | case .iMac16_2:
448 | return "iMac (Retina 4K, 21.5-inch, Late 2015)"
449 | case .iMac16_1:
450 | return "iMac (21.5-inch, Late 2015)"
451 | case .iMac15_1:
452 | /// Need some decision processing
453 | return "iMac (Retina 5K, 27-inch, Mid 2015) / (Retina 5K, 27-inch, Late 2014)"
454 | case .iMac14_4:
455 | return "iMac (21.5-inch, Mid 2014)"
456 | case .iMac14_2:
457 | return "iMac (27-inch, Late 2013)"
458 | case .iMac14_1:
459 | return "iMac (21.5-inch, Late 2013)"
460 | case .iMac13_2:
461 | return "iMac (27-inch, Late 2012)"
462 | case .iMac13_1:
463 | return "iMac (21.5-inch, Late 2012)"
464 |
465 | // MARK: Mac Studio
466 | case .Mac14_13, .Mac14_14:
467 | return "Mac Studio (2023)"
468 | case .Mac13_1, .Mac13_2:
469 | return "Mac Studio (2022)"
470 | }
471 | }
472 | }
473 | }
474 |
475 | // MARK: - MacDeveiceHardware extensions
476 | public extension MacDeviceHardware {
477 | /// get Model Identifier
478 | private func getModelIdentifier() -> String? {
479 | var size: Int = 0
480 | sysctlbyname("hw.model", nil, &size, nil, 0)
481 | var machine = [CChar](repeating: 0, count: Int(size))
482 | if sysctlbyname("hw.model", &machine, &size, nil, 0) != 0 {
483 | return nil
484 | }
485 | let code: String = String(cString:machine)
486 |
487 | return code
488 | }
489 |
490 | // MARK: -
491 | private func getCpuBrandString() -> String? {
492 | var size: Int = 0
493 | sysctlbyname("machdep.cpu.brand_string", nil, &size, nil, 0)
494 | var machine = [CChar](repeating: 0, count: Int(size))
495 | if sysctlbyname("machdep.cpu.brand_string", &machine, &size, nil, 0) != 0 {
496 | return nil
497 | }
498 | let cpuInfo: String = String(cString:machine)
499 |
500 | return cpuInfo
501 | }
502 |
503 |
504 | private func generateIntelCPUString(number: String, frequency: String) -> String {
505 | return "Intel(R) Core(TM) \(number) CPU @ \(frequency)"
506 | }
507 |
508 | /// get Mac model name
509 | private func getModelName() -> String? {
510 | guard let id = getModelIdentifier() else {
511 | return nil
512 | }
513 |
514 | guard let modelId = ModelIdentifier(rawValue: id) else {
515 | return nil
516 | }
517 |
518 | let cpuString = getCpuBrandString() ?? ""
519 |
520 | // same model identifier model
521 | switch modelId {
522 | case .MacBookAir7_2:
523 | switch cpuString {
524 | case generateIntelCPUString(number: "i5-5350U", frequency: "1.80GHz"):
525 | return "MacBook Air (13-inch, 2017)"
526 | case generateIntelCPUString(number: "i5-5250U", frequency: "1.60GHz"):
527 | return "MacBook Air (13-inch, Early 2015)"
528 | default:
529 | // Core i7-5650U or other CPU
530 | return "MacBook Air (13-inch, Early 2017)"
531 | }
532 | case .MacBookAir6_2:
533 | switch cpuString {
534 | case generateIntelCPUString(number: "i5-4260U", frequency: "1.40GHz"):
535 | return "MacBook Air (13-inch, Early 2014)"
536 | case generateIntelCPUString(number: "i5-4250U", frequency: "1.30GHz"):
537 | return "MacBook Air (13-inch, Mid 2013)"
538 | default:
539 | // Core i7-4650U or other CPU
540 | return "MacBook Air (13-inch, Early 2014)"
541 | }
542 | case .MacBookAir6_1:
543 | switch cpuString {
544 | case generateIntelCPUString(number: "i5-4260U", frequency: "1.40GHz"):
545 | return "MacBook Air (11-inch, Early 2014)"
546 | case generateIntelCPUString(number: "i5-4250U", frequency: "1.30GHz"):
547 | return "MacBook Air (11-inch, Mid 2013)"
548 | default:
549 | // Core i7-4650U or other CPU
550 | return "MacBook Air (11-inch, Early 2014)"
551 | }
552 | case .MacBookPro15_1:
553 | switch cpuString {
554 | case generateIntelCPUString(number: "i7-9750H", frequency: "2.60GHz"), generateIntelCPUString(number: "i9-9880H", frequency: "2.30GHz"), generateIntelCPUString(number: "i9-9980HK", frequency: "2.40GHz"):
555 | return "MacBook Pro (15-inch, 2019)"
556 | case generateIntelCPUString(number: "i7-8750H", frequency: "2.20GHz"), generateIntelCPUString(number: "i7-8850H", frequency: "2.60GHz"), generateIntelCPUString(number: "i9-8950HK", frequency: "2.90GHz"):
557 | return "MacBook Pro (15-inch, 2018)"
558 | default:
559 | return "MacBook Pro (15-inch, 2019)"
560 | }
561 | case .MacBookPro15_2:
562 | switch cpuString {
563 | case generateIntelCPUString(number: "i5-8279U", frequency: "2.40GHz"), generateIntelCPUString(number: "i7-8569U", frequency: "2.80GHz"):
564 | return "MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports)"
565 | case generateIntelCPUString(number: "i5-8259U", frequency: "2.30GHz"), generateIntelCPUString(number: "i7-8559U", frequency: "2.70GHz"):
566 | return "MacBook Pro (13-inch, 2018, Four Thunderbolt 3 ports)"
567 | default:
568 | return "MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports)"
569 | }
570 | case .MacBookPro11_3, .MacBookPro11_2:
571 | switch cpuString {
572 | case generateIntelCPUString(number: "i7-4770HQ", frequency: "2.20GHz"), generateIntelCPUString(number: "i7-4870HQ", frequency: "2.50GHz"), generateIntelCPUString(number: "i7-4980HQ", frequency: "2.80GHz"):
573 | return "MacBook Pro (Retina, 15-inch, Mid 2014)"
574 | case generateIntelCPUString(number: "i7-4750HQ", frequency: "2.00GHz"), generateIntelCPUString(number: "i7-4850HQ", frequency: "2.30GHz"), generateIntelCPUString(number: "i7-4960HQ", frequency: "2.60GHz"):
575 | return "MacBook Pro (Retina, 15-inch, Late 2013)"
576 | default:
577 | return "MacBook Pro (Retina, 15-inch, Mid 2014)"
578 | }
579 | case .MacBookPro11_1:
580 | switch cpuString {
581 | case generateIntelCPUString(number: "i5-4278U", frequency: "2.60GHz"), generateIntelCPUString(number: "i5-4308U", frequency: "2.80GHz"), generateIntelCPUString(number: "i7-4578U", frequency: "3.00GHz"):
582 | return "MacBook Pro (Retina, 13-inch, Mid 2014)"
583 | case generateIntelCPUString(number: "i5-4258U", frequency: "2.40GHz"), generateIntelCPUString(number: "i5-4288U", frequency: "2.60GHz"), generateIntelCPUString(number: "i7-4558U", frequency: "3.00GHz"):
584 | return "MacBook Pro (Retina, 13-inch, Late 2013)"
585 | default:
586 | return "MacBook Pro (Retina, 13-inch, Mid 2014)"
587 | }
588 | case .iMac15_1:
589 | switch cpuString {
590 | case generateIntelCPUString(number: "i5-4590", frequency: "3.30GHz"):
591 | return "iMac (Retina 5K, 27-inch, Mid 2015)"
592 | case generateIntelCPUString(number: "i5-4690", frequency: "3.50GHz"), generateIntelCPUString(number: "i7-4790K", frequency: "4.00GHz"):
593 | return "iMac (Retina 5K, 27-inch, Late 2014)"
594 | default:
595 | return "iMac (Retina 5K, 27-inch, Mid 2015)"
596 | }
597 | default:
598 | // other model
599 | return modelId.modelName()
600 | }
601 | }
602 |
603 | // MARK: -
604 | /// get processor name
605 | private func getProcessorName() -> String? {
606 | guard let cpuInfo = getCpuBrandString() else {
607 | return nil
608 | }
609 |
610 | let cpuInfoArray = cpuInfo.split(separator: "@")
611 | let cpuBrand = cpuInfoArray[0]
612 | .replacingOccurrences(of: "CPU", with: "")
613 | .replacingOccurrences(of: "(R)", with: "")
614 | .replacingOccurrences(of: "(TM)", with: "")
615 | .trimmingCharacters(in: .whitespaces)
616 |
617 | return cpuBrand
618 | }
619 |
620 | /// get the number of physical core
621 | private func getPhysicalCore() -> Int? {
622 | var core: Int32 = 0
623 | var size = MemoryLayout.size
624 |
625 | if sysctlbyname("hw.physicalcpu", &core, &size, nil, 0) != 0 {
626 | return nil
627 | }
628 |
629 | return Int(core)
630 | }
631 |
632 | /// Returns true if running on Apple Silicon Mac (arm64), false otherwise.
633 | func isAppleSiliconMac() -> Bool? {
634 | var isARM: Int32 = 0
635 | var size = MemoryLayout.size
636 | if sysctlbyname("hw.optional.arm64", &isARM, &size, nil, 0) != 0 {
637 | return nil
638 | }
639 | return isARM == 1
640 | }
641 |
642 | /// get CPU info
643 | private func getCpu() -> String? {
644 | guard let id = getModelIdentifier() else {
645 | return nil
646 | }
647 |
648 | guard let modelId = ModelIdentifier(rawValue: id) else {
649 | return nil
650 | }
651 |
652 | // TODO: Add CPU frequency when new Apple Silicon Series is announced.
653 | // MARK: Apple silicon or not
654 | if isAppleSiliconMac() != nil {
655 | guard let core = getPhysicalCore() else {
656 | return nil
657 | }
658 |
659 | switch modelId {
660 | /// M1 family
661 | case .MacBookAir10_1, .MacBookPro17_1, .Macmini9_1, .iMac21_1, .iMac21_2,
662 | .MacBookPro18_1, .MacBookPro18_2, .MacBookPro18_3, .MacBookPro18_4, .Mac13_1, .Mac13_2:
663 | return "3.2GHz \(core)-core"
664 | /// M2 family
665 | case .Mac14_2, .Mac14_7, .Mac14_3, .Mac14_15, .Mac14_5, .Mac14_6, .Mac14_9, .Mac14_10, .Mac14_12, .Mac14_13, .Mac14_14, .Mac14_8:
666 | return "3.49GHz \(core)-core"
667 | /// M3 family
668 | case .Mac15_3, .Mac15_4, .Mac15_5, .Mac15_6, .Mac15_7, .Mac15_8, .Mac15_9, .Mac15_10, .Mac15_11, .Mac15_12, .Mac15_13:
669 | return "4.05GHz \(core)-core"
670 | /// M4
671 | case .Mac16_1, .Mac16_2, .Mac16_3, .Mac16_10, .Mac16_12, .Mac16_13:
672 | return "4.4GHz \(core)-core"
673 | /// M4 Pro, M4 Max
674 | case .Mac16_5, .Mac16_6, .Mac16_7, .Mac16_8, .Mac16_15:
675 | return "4.51GHz \(core)-core"
676 | /// M5
677 | case .Mac17_2:
678 | return "4.61GHz \(core)-core"
679 | default:
680 | return nil
681 | }
682 | } else {
683 | // Intel CPU Information
684 | guard let cpuInfo = getCpuBrandString() else {
685 | return nil
686 | }
687 |
688 | let cpuInfoArray = cpuInfo.split(separator: "@")
689 | let cpuFrequency = cpuInfoArray[1].trimmingCharacters(in: .whitespaces)
690 |
691 | guard let core = getPhysicalCore() else {
692 | return nil
693 | }
694 |
695 | return "\(cpuFrequency) \(core)-core"
696 | }
697 | }
698 |
699 | /// get neural engine info
700 | private func getNeuralEngine() -> String? {
701 | guard let id = getModelIdentifier() else {
702 | return nil
703 | }
704 |
705 | guard let modelId = ModelIdentifier(rawValue: id) else {
706 | return nil
707 | }
708 |
709 | return modelId.neuralEngine()
710 | }
711 | }
712 |
713 |
--------------------------------------------------------------------------------
/Sources/DeviceHardware/UIDeviceHardware.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public class UIDeviceHardware: DeviceHardware {
4 | public static let deviceHardware = UIDeviceHardware()
5 |
6 | /// model name, such as iPhone 8
7 | public var modelName: String {
8 | let modelName_ = getModelName() ?? "Unknown"
9 | return modelName_
10 | }
11 | /// processor name, such as A11 Bionic
12 | public var processorName: String {
13 | let processorName_ = getProcessorName() ?? "Unknown"
14 | return processorName_
15 | }
16 | /// CPU information, such as 2.39GHz 6-core
17 | public var cpu: String {
18 | let cpu_ = getCpu() ?? "Unknown"
19 | return cpu_
20 | }
21 | /// GPU information, such as Apple A11 GPU
22 | public var gpu: String {
23 | let gpu_ = getGpu() ?? "Unknown"
24 | return gpu_
25 | }
26 | /// Neural Engine, such as 2-core
27 | public var neuralEngine: String {
28 | let neuralEngine_ = getNeuralEngine() ?? "Unknown"
29 | return neuralEngine_
30 | }
31 |
32 | /// Model Identifier, such as iPhone10,1
33 | public var modelIdentifier: String {
34 | let modelId = getModelIdentifier() ?? "Unknown"
35 | return modelId
36 | }
37 | /// number of processor, such as 6
38 | public var processorCount: Int {
39 | return ProcessInfo.processInfo.processorCount
40 | }
41 | /// physical memory size [B], such as 2071019520
42 | public var ram: Int {
43 | return getRAM()
44 | }
45 | /// physical memory size, such as 2GB
46 | public var ramString: String {
47 | return getRAMString()
48 | }
49 | /// The device has Dynamic Island
50 | public var hasDynamicIsland: Bool {
51 | return getHasDynamicIsland() ?? false
52 | }
53 |
54 | // MARK: -
55 | private func getModelIdentifier() -> String? {
56 | var size: Int = 0
57 | sysctlbyname("hw.machine", nil, &size, nil, 0)
58 | var machine = [CChar](repeating: 0, count: Int(size))
59 | if sysctlbyname("hw.machine", &machine, &size, nil, 0) != 0 {
60 | return nil
61 | }
62 | let code: String = String(cString:machine)
63 |
64 | return code
65 | }
66 |
67 | private func getModelName() -> String? {
68 | guard let id = getModelIdentifier() else {
69 | return nil
70 | }
71 |
72 | guard let modelId = ModelIdentifier(rawValue: id) else {
73 | return nil
74 | }
75 |
76 | return modelId.modelName()
77 | }
78 |
79 | private func getProcessorName() -> String? {
80 | guard let id = getModelIdentifier() else {
81 | return nil
82 | }
83 |
84 | guard let modelId = ModelIdentifier(rawValue: id) else {
85 | return nil
86 | }
87 |
88 | return modelId.processorName()
89 | }
90 |
91 | private func getCpu() -> String? {
92 | guard let id = getModelIdentifier() else {
93 | return nil
94 | }
95 |
96 | guard let modelId = ModelIdentifier(rawValue: id) else {
97 | return nil
98 | }
99 |
100 | return modelId.cpu()
101 | }
102 |
103 | private func getGpu() -> String? {
104 | if #available(OSX 10.11, iOS 8.0, macCatalyst 13.0, *) {
105 | return getMetalGpu()
106 | } else {
107 | // Fallback on earlier versions
108 | guard let id = getModelIdentifier() else {
109 | return nil
110 | }
111 |
112 | guard let modelId = ModelIdentifier(rawValue: id) else {
113 | return nil
114 | }
115 |
116 | return modelId.gpu()
117 | }
118 | }
119 |
120 | private func getNeuralEngine() -> String? {
121 | guard let id = getModelIdentifier() else {
122 | return nil
123 | }
124 |
125 | guard let modelId = ModelIdentifier(rawValue: id) else {
126 | return nil
127 | }
128 |
129 | return modelId.neuralEngine()
130 | }
131 |
132 | private func getHasDynamicIsland() -> Bool? {
133 | guard let id = getModelIdentifier() else {
134 | return nil
135 | }
136 |
137 | guard let modelId = ModelIdentifier(rawValue: id) else {
138 | return nil
139 | }
140 |
141 | return modelId.hasDynamicIsland()
142 | }
143 |
144 | // MARK: -
145 | enum ModelIdentifier: String {
146 | // MARK: Simulator
147 | case i386
148 | case x86_64
149 | case arm64
150 | // MARK: iPod
151 | /// iPod touch (1st Generation)
152 | case iPod1_1 = "iPod1,1"
153 | /// iPod touch (2nd Generation)
154 | case iPod2_1 = "iPod2,1"
155 | /// iPod touch (3rd Generation)
156 | case iPod3_1 = "iPod3,1"
157 | /// iPod touch (4th Generation)
158 | case iPod4_1 = "iPod4,1"
159 | /// iPod touch (5th Generation)
160 | case iPod5_1 = "iPod5,1"
161 | /// iPod touch (6th Generation)
162 | case iPod7_1 = "iPod7,1"
163 | /// iPod touch (7th Generation)
164 | case iPod9_1 = "iPod9,1"
165 |
166 | // MARK: iPhone
167 | /// iPhone
168 | case iPhone1_1 = "iPhone1,1"
169 | /// iPhone 3G
170 | case iPhone1_2 = "iPhone1,2"
171 | /// iPhone 3GS
172 | case iPhone2_1 = "iPhone2,1"
173 | /// iPhone 4 GSM
174 | case iPhone3_1 = "iPhone3,1"
175 | /// iPhone 4 GSM 2012
176 | case iPhone3_2 = "iPhone3,2"
177 | /// iPhone 4 CDMA For Verizon,Sprint
178 | case iPhone3_3 = "iPhone3,3"
179 | /// iPhone 4S
180 | case iPhone4_1 = "iPhone4,1"
181 | /// iPhone 5 GSM
182 | case iPhone5_1 = "iPhone5,1"
183 | /// iPhone 5 Global
184 | case iPhone5_2 = "iPhone5,2"
185 | /// iPhone 5c GSM
186 | case iPhone5_3 = "iPhone5,3"
187 | /// iPhone 5c Global
188 | case iPhone5_4 = "iPhone5,4"
189 | /// iPhone 5s GSM
190 | case iPhone6_1 = "iPhone6,1"
191 | /// iPhone 5s Global
192 | case iPhone6_2 = "iPhone6,2"
193 | /// iPhone 6 Plus
194 | case iPhone7_1 = "iPhone7,1"
195 | /// iPhone 6
196 | case iPhone7_2 = "iPhone7,2"
197 | /// iPhone 6S
198 | case iPhone8_1 = "iPhone8,1"
199 | /// iPhone 6S Plus
200 | case iPhone8_2 = "iPhone8,2"
201 | /// iPhone SE
202 | case iPhone8_4 = "iPhone8,4"
203 | /// iPhone 7 A1660,A1779,A1780
204 | case iPhone9_1 = "iPhone9,1"
205 | /// iPhone 7 A1778
206 | case iPhone9_3 = "iPhone9,3"
207 | /// iPhone 7 Plus A1661,A1785,A1786
208 | case iPhone9_2 = "iPhone9,2"
209 | /// iPhone 7 Plus A1784
210 | case iPhone9_4 = "iPhone9,4"
211 | /// iPhone 8 A1863,A1906,A1907
212 | case iPhone10_1 = "iPhone10,1"
213 | /// iPhone 8 A1905
214 | case iPhone10_4 = "iPhone10,4"
215 | /// iPhone 8 Plus A1864,A1898,A1899
216 | case iPhone10_2 = "iPhone10,2"
217 | /// iPhone 8 Plus A1897
218 | case iPhone10_5 = "iPhone10,5"
219 | /// iPhone X A1865,A1902
220 | case iPhone10_3 = "iPhone10,3"
221 | /// iPhone X A1901
222 | case iPhone10_6 = "iPhone10,6"
223 | /// iPhone XR A1984,A2105,A2106,A2108
224 | case iPhone11_8 = "iPhone11,8"
225 | /// iPhone XS A2097,A2098
226 | case iPhone11_2 = "iPhone11,2"
227 | /// iPhone XS Max A1921,A2103
228 | case iPhone11_4 = "iPhone11,4"
229 | /// iPhone XS Max A2104
230 | case iPhone11_6 = "iPhone11,6"
231 | /// iPhone 11
232 | case iPhone12_1 = "iPhone12,1"
233 | /// iPhone 11 Pro
234 | case iPhone12_3 = "iPhone12,3"
235 | /// iPhone 11 Pro Max
236 | case iPhone12_5 = "iPhone12,5"
237 | /// iPhone SE (2nd Generation)
238 | case iPhone12_8 = "iPhone12,8"
239 | /// iPhone 12 mini
240 | case iPhone13_1 = "iPhone13,1"
241 | /// iPhone 12
242 | case iPhone13_2 = "iPhone13,2"
243 | /// iPhone 12 Pro
244 | case iPhone13_3 = "iPhone13,3"
245 | /// iPhone 12 Pro Max
246 | case iPhone13_4 = "iPhone13,4"
247 | /// iPhone 13 mini
248 | case iPhone14_4 = "iPhone14,4"
249 | /// iPhone 13
250 | case iPhone14_5 = "iPhone14,5"
251 | /// iPhone 13 Pro
252 | case iPhone14_2 = "iPhone14,2"
253 | /// iPhone 13 Pro Max
254 | case iPhone14_3 = "iPhone14,3"
255 | /// iPhone SE (3rg generation)
256 | case iPhone14_6 = "iPhone14,6"
257 | /// iPhone 14
258 | case iPhone14_7 = "iPhone14,7"
259 | /// iPhone 14 Plus
260 | case iPhone14_8 = "iPhone14,8"
261 | /// iPhone 14 Pro
262 | case iPhone15_2 = "iPhone15,2"
263 | /// iPhone 14 Pro Max
264 | case iPhone15_3 = "iPhone15,3"
265 | /// iPhone 15
266 | case iPhone15_4 = "iPhone15,4"
267 | /// iPhone 15 Plus
268 | case iPhone15_5 = "iPhone15,5"
269 | /// iPhone 15 Pro
270 | case iPhone16_1 = "iPhone16,1"
271 | /// iPhone 15 Pro Max
272 | case iPhone16_2 = "iPhone16,2"
273 | /// iPhone 16
274 | case iPhone17_3 = "iPhone17,3"
275 | /// iPhone 16 Plus
276 | case iPhone17_4 = "iPhone17,4"
277 | /// iPhone 16 Pro
278 | case iPhone17_1 = "iPhone17,1"
279 | /// iPhone 16 Pro Max
280 | case iPhone17_2 = "iPhone17,2"
281 | /// iPhone 16e
282 | case iPhone17_5 = "iPhone17,5"
283 | /// iPhone 17
284 | case iPhone18_3 = "iPhone18,3"
285 | /// iPhone 17 Pro
286 | case iPhone18_1 = "iPhone18,1"
287 | /// iPhone 17 Pro Max
288 | case iPhone18_2 = "iPhone18,2"
289 | /// iPhone Air
290 | case iPhone18_4 = "iPhone18,4"
291 |
292 | // MARK: iPad
293 | /// iPad
294 | case iPad1_1 = "iPad1,1"
295 | /// iPad 2
296 | case iPad2_1 = "iPad2,1"
297 | /// iPad 2 GSM
298 | case iPad2_2 = "iPad2,2"
299 | /// iPad 2 CDMA (Cellular)
300 | case iPad2_3 = "iPad2,3"
301 | /// iPad 2 Mid2012
302 | case iPad2_4 = "iPad2,4"
303 | /// iPad mini WiFi
304 | case iPad2_5 = "iPad2,5"
305 | /// iPad mini GSM (Cellular)
306 | case iPad2_6 = "iPad2,6"
307 | /// iPad mini Global (Cellular)
308 | case iPad2_7 = "iPad2,7"
309 | /// iPad 3 WiFi
310 | case iPad3_1 = "iPad3,1"
311 | /// iPad 3 CDMA (Cellular)
312 | case iPad3_2 = "iPad3,2"
313 | /// iPad 3 GSM (Cellular)
314 | case iPad3_3 = "iPad3,3"
315 | /// iPad 4 WiFi
316 | case iPad3_4 = "iPad3,4"
317 | /// iPad 4 GSM (Cellular)
318 | case iPad3_5 = "iPad3,5"
319 | /// iPad 4 Global (Cellular)
320 | case iPad3_6 = "iPad3,6"
321 | /// iPad Air WiFi
322 | case iPad4_1 = "iPad4,1"
323 | /// iPad Air Cellular
324 | case iPad4_2 = "iPad4,2"
325 | /// iPad Air ChinaModel
326 | case iPad4_3 = "iPad4,3"
327 | /// iPad mini 2 WiFi
328 | case iPad4_4 = "iPad4,4"
329 | /// iPad mini 2 Cellular
330 | case iPad4_5 = "iPad4,5"
331 | /// iPad mini 2 ChinaModel
332 | case iPad4_6 = "iPad4,6"
333 | /// iPad mini 3 WiFi
334 | case iPad4_7 = "iPad4,7"
335 | /// iPad mini 3 Cellular
336 | case iPad4_8 = "iPad4,8"
337 | /// iPad mini 3 ChinaModel
338 | case iPad4_9 = "iPad4,9"
339 | /// iPad mini 4 WiFi
340 | case iPad5_1 = "iPad5,1"
341 | /// iPad mini 4 Cellular
342 | case iPad5_2 = "iPad5,2"
343 | /// iPad Air 2 WiFi
344 | case iPad5_3 = "iPad5,3"
345 | /// iPad Air 2 Cellular
346 | case iPad5_4 = "iPad5,4"
347 | /// iPad Pro 9.7inch WiFi
348 | case iPad6_3 = "iPad6,3"
349 | /// iPad Pro 9.7inch Cellular
350 | case iPad6_4 = "iPad6,4"
351 | /// iPad Pro 12.9inch WiFi
352 | case iPad6_7 = "iPad6,7"
353 | /// iPad Pro 12.9inch Cellular
354 | case iPad6_8 = "iPad6,8"
355 | /// iPad (5th Generation) WiFi
356 | case iPad6_11 = "iPad6,11"
357 | /// iPad (5th Generation) Cellular
358 | case iPad6_12 = "iPad6,12"
359 | /// iPad Pro 12.9inch (2nd Generation) WiFi
360 | case iPad7_1 = "iPad7,1"
361 | /// iPad Pro 12.9inch (2nd Generation) Cellular
362 | case iPad7_2 = "iPad7,2"
363 | /// iPad Pro 10.5inch A1701 WiFi
364 | case iPad7_3 = "iPad7,3"
365 | /// iPad Pro 10.5inch A1709 Cellular
366 | case iPad7_4 = "iPad7,4"
367 | /// iPad 6th Generation WiFi
368 | case iPad7_5 = "iPad7,5"
369 | /// iPad 6th Generation Cellular
370 | case iPad7_6 = "iPad7,6"
371 | /// iPad 7th Generation WiFi
372 | case iPad7_11 = "iPad7,11"
373 | /// iPad 7th Generation Cellular
374 | case iPad7_12 = "iPad7,12"
375 | /// iPad Pro 11inch WiFi
376 | case iPad8_1 = "iPad8,1"
377 | /// iPad Pro 11inch WiFi
378 | case iPad8_2 = "iPad8,2"
379 | /// iPad Pro 11inch Cellular
380 | case iPad8_3 = "iPad8,3"
381 | /// iPad Pro 11inch Cellular
382 | case iPad8_4 = "iPad8,4"
383 | /// iPad Pro 12.9inch WiFi
384 | case iPad8_5 = "iPad8,5"
385 | /// iPad Pro 12.9inch WiFi
386 | case iPad8_6 = "iPad8,6"
387 | /// iPad Pro 12.9inch Cellular
388 | case iPad8_7 = "iPad8,7"
389 | /// iPad Pro 12.9inch Cellular
390 | case iPad8_8 = "iPad8,8"
391 | /// iPad Pro 11inch (2nd generation) WiFi
392 | case iPad8_9 = "iPad8,9"
393 | /// iPad Pro 11inch (2nd generation) Cellular
394 | case iPad8_10 = "iPad8,10"
395 | /// iPad Pro 12.9inch (4th generation) WiFi
396 | case iPad8_11 = "iPad8,11"
397 | /// iPad Pro 12.9inch (4th generation) Cellular
398 | case iPad8_12 = "iPad8,12"
399 | /// iPad mini 5th WiFi
400 | case iPad11_1 = "iPad11,1"
401 | /// iPad mini 5th Cellular
402 | case iPad11_2 = "iPad11,2"
403 | /// iPad Air (3rd generation) WiFi
404 | case iPad11_3 = "iPad11,3"
405 | /// iPad Air (3rd generation) Cellular
406 | case iPad11_4 = "iPad11,4"
407 | /// iPad (8th generation) WiFi
408 | case iPad11_6 = "iPad11,6"
409 | /// iPad (8th generation) Cellular
410 | case iPad11_7 = "iPad11,7"
411 | /// iPad Air (4th generation) WiFi
412 | case iPad13_1 = "iPad13,1"
413 | /// iPad Air (4th generation) Cellular
414 | case iPad13_2 = "iPad13,2"
415 | /// iPad Pro 11-inch (3rd generation)
416 | case iPad13_4 = "iPad13,4"
417 | case iPad13_5 = "iPad13,5"
418 | case iPad13_6 = "iPad13,6"
419 | case iPad13_7 = "iPad13,7"
420 | /// iPad Pro 12.9-inch (5th generation)
421 | case iPad13_8 = "iPad13,8"
422 | case iPad13_9 = "iPad13,9"
423 | case iPad13_10 = "iPad13,10"
424 | case iPad13_11 = "iPad13,11"
425 | /// iPad (9th generation) Wi-Fi + Cellular
426 | case iPad12_2 = "iPad12,2"
427 | /// iPad (9th generation) Wi-Fi
428 | case iPad12_1 = "iPad12,1"
429 | /// iPad mini (6th generation) Wi-Fi + Cellular
430 | case iPad14_2 = "iPad14,2"
431 | /// iPad mini (6th generation) Wi-Fi
432 | case iPad14_1 = "iPad14,1"
433 | /// iPad Air (5th generation)
434 | case iPad13_16 = "iPad13,16"
435 | case iPad13_17 = "iPad13,17"
436 | /// iPad (10th generation)
437 | case iPad13_18 = "iPad13,18"
438 | case iPad13_19 = "iPad13,19"
439 | /// iPad Pro 11-inch (4th generation)
440 | case iPad14_3_A = "iPad14,3-A"
441 | case iPad14_3_B = "iPad14,3-B"
442 | case iPad14_4_A = "iPad14,4-A"
443 | case iPad14_4_B = "iPad14,4-B"
444 | /// iPad Pro 12.9-inch (6th generation)
445 | case iPad14_5_A = "iPad14,5-A"
446 | case iPad14_5_B = "iPad14,5-B"
447 | case iPad14_6_A = "iPad14,6-A"
448 | case iPad14_6_B = "iPad14,6-B"
449 | /// iPad Air 11-inch (6th generation) Wi-Fi
450 | case iPad14_8 = "iPad14,8"
451 | /// iPad Air 11-inch (6th generation) Wi-Fi + Cellular
452 | case iPad14_9 = "iPad14,9"
453 | /// iPad Air 13-inch (6th generation) Wi-Fi
454 | case iPad14_10 = "iPad14,10"
455 | /// iPad Air 13-inch (6th generation) Wi-Fi + Cellular
456 | case iPad14_11 = "iPad14,11"
457 | /// iPad Pro 11-inch M4 Wi-Fi
458 | case iPad16_3 = "iPad16,3"
459 | /// iPad Pro 11-inch M4 Wi-Fi + Cellular
460 | case iPad16_4 = "iPad16,4"
461 | /// iPad Pro 13-inch M4 Wi-Fi
462 | case iPad16_5 = "iPad16,5"
463 | /// iPad Pro 13-inch M4 Wi-Fi + Cellular
464 | case iPad16_6 = "iPad16,6"
465 | /// iPad mini (A17 Pro)
466 | case iPad16_1 = "iPad16,1"
467 | case iPad16_2 = "iPad16,2"
468 | /// iPad Pro 11-inch (M5, 2025) Wi-Fi
469 | case iPad17_1 = "iPad17,1"
470 | /// iPad Pro 11-inch (M5, 2025) Wi-Fi + Cellular
471 | case iPad17_2 = "iPad17,2"
472 | /// iPad Pro 13-inch (M5, 2025) Wi-Fi
473 | case iPad17_3 = "iPad17,3"
474 | /// iPad Pro 13-inch (M5, 2025) Wi-Fi + Cellular
475 | case iPad17_4 = "iPad17,4"
476 |
477 | /// model name
478 | func modelName() -> String {
479 | switch self {
480 | case .i386, .x86_64, .arm64:
481 | return "Simulator"
482 | case .iPod1_1:
483 | return "iPod touch (1st generation)"
484 | case .iPod2_1:
485 | return "iPod touch (2nd generation)"
486 | case .iPod3_1:
487 | return "iPod touch (3rd generation)"
488 | case .iPod4_1:
489 | return "iPod touch (4th generation)"
490 | case .iPod5_1:
491 | return "iPod touch (5th generation)"
492 | case .iPod7_1:
493 | return "iPod touch (6th generation)"
494 | case .iPod9_1:
495 | return "iPod touch (7th generation)"
496 | case .iPhone1_1:
497 | return "iPhone (the original iPhone)"
498 | case .iPhone1_2:
499 | return "iPhone 3G"
500 | case .iPhone2_1:
501 | return "iPhone 3GS"
502 | case .iPhone3_1, .iPhone3_2, .iPhone3_3:
503 | return "iPhone4"
504 | case .iPhone4_1:
505 | return "iPhone 4S"
506 | case .iPhone5_1, .iPhone5_2:
507 | return "iPhone 5"
508 | case .iPhone5_3, .iPhone5_4:
509 | return "iPhone 5c"
510 | case .iPhone6_1, .iPhone6_2:
511 | return "iPhone 5s"
512 | case .iPhone7_1:
513 | return "iPhone 6 Plus"
514 | case .iPhone7_2:
515 | return "iPhone 6"
516 | case .iPhone8_1:
517 | return "iPhone 6s"
518 | case .iPhone8_2:
519 | return "iPhone 6s Plus"
520 | case .iPhone8_4:
521 | return "iPhone SE (1th generation)"
522 | case .iPhone9_1, .iPhone9_3:
523 | return "iPhone 7"
524 | case .iPhone9_2, .iPhone9_4:
525 | return "iPhone 7 Plus"
526 | case .iPhone10_1, .iPhone10_4:
527 | return "iPhone 8"
528 | case .iPhone10_2, .iPhone10_5:
529 | return "iPhone 8 Plus"
530 | case .iPhone10_3, .iPhone10_6:
531 | return "iPhone X"
532 | case .iPhone11_8:
533 | return "iPhone XR"
534 | case .iPhone11_2:
535 | return "iPhone XS"
536 | case .iPhone11_4, .iPhone11_6:
537 | return "iPhone XS Max"
538 | case .iPhone12_1:
539 | return "iPhone 11"
540 | case .iPhone12_3:
541 | return "iPhone 11 Pro"
542 | case .iPhone12_5:
543 | return "iPhone 11 Pro Max"
544 | case .iPhone12_8:
545 | return "iPhone SE (2nd generation)"
546 | case .iPhone13_1:
547 | return "iPhone 12 mini"
548 | case .iPhone13_2:
549 | return "iPhone 12"
550 | case .iPhone13_3:
551 | return "iPhone 12 Pro"
552 | case .iPhone13_4:
553 | return "iPhone 12 Pro Max"
554 | case .iPad1_1:
555 | return "iPad (1st generation)"
556 | case .iPad2_1, .iPad2_4, .iPad2_2, .iPad2_3:
557 | return "iPad 2"
558 | case .iPad2_5, .iPad2_6, .iPad2_7:
559 | return "iPad mini"
560 | case .iPad3_1, .iPad3_2, .iPad3_3:
561 | return "iPad (3rd generation) (The new iPad)"
562 | case .iPad3_4, .iPad3_5, .iPad3_6:
563 | return "iPad (4th generation) (iPad with Retina display)"
564 | case .iPad4_1, .iPad4_2, .iPad4_3:
565 | return "iPad Air (1th generation)"
566 | case .iPad4_4, .iPad4_5, .iPad4_6:
567 | return "iPad mini 2"
568 | case .iPad4_7, .iPad4_8, .iPad4_9:
569 | return "iPad mini 3"
570 | case .iPad5_1, .iPad5_2:
571 | return "iPad mini 4"
572 | case .iPad5_3, .iPad5_4:
573 | return "iPad Air 2"
574 | case .iPad6_3, .iPad6_4:
575 | return "iPad Pro (9.7-inch)"
576 | case .iPad6_7, .iPad6_8:
577 | return "iPad Pro (12.9-inch) (1st generation)"
578 | case .iPad6_11, .iPad6_12:
579 | return "iPad (5th generation)"
580 | case .iPad7_1, .iPad7_2:
581 | return "iPad Pro (12.9-inch) (2nd generation)"
582 | case .iPad7_3, .iPad7_4:
583 | return "iPad Pro (10.5-inch)"
584 | case .iPad7_5, .iPad7_6:
585 | return "iPad (6th generation)"
586 | case .iPad7_11, .iPad7_12:
587 | return "iPad (7th generation)"
588 | case .iPad8_1, .iPad8_2, .iPad8_3, .iPad8_4:
589 | return "iPad Pro (11-inch)"
590 | case .iPad8_5, .iPad8_6, .iPad8_7, .iPad8_8:
591 | return "iPad Pro (12.9-inch) (3rd generation)"
592 | case .iPad8_9, .iPad8_10:
593 | return "iPad Pro (11-inch) (2nd generation)"
594 | case .iPad8_11, .iPad8_12:
595 | return "iPad Pro (12.9-inch) (4th generation)"
596 | case .iPad11_1, .iPad11_2:
597 | return "iPad mini (5th generation)"
598 | case .iPad11_3, .iPad11_4:
599 | return "iPad Air (3rd generation)"
600 | case .iPad11_6, .iPad11_7:
601 | return "iPad (8th generation)"
602 | case .iPad13_1, .iPad13_2:
603 | return "iPad Air (4th generation)"
604 | case .iPad13_4, .iPad13_5, .iPad13_6, .iPad13_7:
605 | return "iPad Pro (11-inch) (3rd generation)"
606 | case .iPad13_8, .iPad13_9, .iPad13_10, .iPad13_11:
607 | return "iPad Pro (12.9-inch) (5th generation)"
608 | case .iPhone14_4:
609 | return "iPhone 13 mini"
610 | case .iPhone14_5:
611 | return "iPhone 13"
612 | case .iPhone14_2:
613 | return "iPhone 13 Pro"
614 | case .iPhone14_3:
615 | return "iPhone 13 Pro Max"
616 | case .iPad12_2, .iPad12_1:
617 | return "iPad (9th generation)"
618 | case .iPad14_2, .iPad14_1:
619 | return "iPad mini (6th generation)"
620 | case .iPhone14_6:
621 | return "iPhone SE (3rd generation)"
622 | case .iPad13_16, .iPad13_17:
623 | return "iPad Air (5th generation)"
624 | case .iPhone14_7:
625 | return "iPhone 14"
626 | case .iPhone14_8:
627 | return "iPhone 14 Plus"
628 | case .iPhone15_2:
629 | return "iPhone 14 Pro"
630 | case .iPhone15_3:
631 | return "iPhone 14 Pro Max"
632 | case .iPad13_18, .iPad13_19:
633 | return "iPad (10th generation)"
634 | case .iPad14_3_A, .iPad14_3_B, .iPad14_4_A, .iPad14_4_B:
635 | return "iPad Pro (11-inch) (4th generation)"
636 | case .iPad14_5_A, .iPad14_5_B, .iPad14_6_A, .iPad14_6_B:
637 | return "iPad Pro (12.9-inch) (6th generation)"
638 | case .iPhone15_4:
639 | return "iPhone 15"
640 | case .iPhone15_5:
641 | return "iPhone 15 Plus"
642 | case .iPhone16_1:
643 | return "iPhone 15 Pro"
644 | case .iPhone16_2:
645 | return "iPhone 15 Pro Max"
646 | case .iPad14_8, .iPad14_9:
647 | return "iPad Air (6th generation) (11-inch)"
648 | case .iPad14_10, .iPad14_11:
649 | return "iPad Air (6th generation) (13-inch)"
650 | case .iPad16_3, .iPad16_4:
651 | return "iPad Pro (M4) (11-inch)"
652 | case .iPad16_5, .iPad16_6:
653 | return "iPad Pro (M4) (13-inch)"
654 | case .iPhone17_3:
655 | return "iPhone 16"
656 | case .iPhone17_4:
657 | return "iPhone 16 Plus"
658 | case .iPhone17_1:
659 | return "iPhone 16 Pro"
660 | case .iPhone17_2:
661 | return "iPhone 16 Pro Max"
662 | case .iPad16_1, .iPad16_2:
663 | return "iPad mini (A17 Pro)"
664 | case .iPhone17_5:
665 | return "iPhone 16e"
666 | case .iPhone18_1:
667 | return "iPhone 17 Pro"
668 | case .iPhone18_2:
669 | return "iPhone 17 Pro Max"
670 | case .iPhone18_3:
671 | return "iPhone 17"
672 | case .iPhone18_4:
673 | return "iPhone Air"
674 | case .iPad17_1, .iPad17_2:
675 | return "iPad Pro (M5) (11-inch)"
676 | case .iPad17_3, .iPad17_4:
677 | return "iPad Pro (M5) (13-inch)"
678 | }
679 | }
680 |
681 | // Processor (SoC) Name
682 | func processorName() -> String {
683 | switch self {
684 | /// Simulator
685 | case .i386, .x86_64, .arm64:
686 | return "N/A"
687 | /// iPhone, iPod touch (1st), iPhone 3G
688 | case .iPod1_1, .iPhone1_1, .iPhone1_2:
689 | return "APL0098"
690 | /// iPod touch (2nd)
691 | case .iPod2_1:
692 | return "APL0278"
693 | /// iPhone 3GS
694 | case .iPhone2_1:
695 | return "APL0298"
696 | /// iPod touch (3rd)
697 | case .iPod3_1:
698 | return "APL2298"
699 | /// iPhone 4, iPad (1st), iPod touch (4th)
700 | case .iPod4_1, .iPhone3_1, .iPhone3_2, .iPhone3_3, .iPad1_1:
701 | return "Apple A4"
702 | /// iPhone 4s, iPad 2, iPod touch (5th), iPad mini (1st)
703 | case .iPhone4_1, .iPod5_1, .iPad2_5, .iPad2_6, .iPad2_7, .iPad2_1, .iPad2_2, .iPad2_3, .iPad2_4:
704 | return "Apple A5"
705 | /// iPad (3rd)
706 | case .iPad3_1, .iPad3_2, .iPad3_3:
707 | return "Apple A5X"
708 | /// iPhone 5, iPhone 5c
709 | case .iPhone5_1, .iPhone5_2, .iPhone5_3, .iPhone5_4:
710 | return "Apple A6"
711 | /// iPad (4th)
712 | case .iPad3_4, .iPad3_5, .iPad3_6:
713 | return "Apple A6X"
714 | /// iPhone 5s, iPad mini 2, iPad mini 3, iPad Air (1st)
715 | case .iPhone6_1, .iPhone6_2, .iPad4_4, .iPad4_5, .iPad4_6, .iPad4_7, .iPad4_8, .iPad4_9, .iPad4_1, .iPad4_2, .iPad4_3:
716 | return "Apple A7"
717 | /// iPhone 6/6 Plus, iPod touch (6th), iPad mini 4
718 | case .iPhone7_1, .iPhone7_2, .iPod7_1, .iPad5_1, .iPad5_2:
719 | return "Apple A8"
720 | /// iPad Air (2nd)
721 | case .iPad5_4, .iPad5_3:
722 | return "Apple A8X"
723 | /// iPhone 6s/6s Plus, iPhone SE (1st), iPad (5th)
724 | case .iPhone8_1, .iPhone8_2, .iPhone8_4, .iPad6_11, .iPad6_12:
725 | return "Apple A9"
726 | /// iPad Pro (1st)
727 | case .iPad6_3, .iPad6_4, .iPad6_7, .iPad6_8:
728 | return "Apple A9X"
729 | /// iPhone 7/7 Plus, iPad (6th), iPod touch (7th), iPad (7th)
730 | case .iPhone9_1, .iPhone9_2, .iPhone9_3, .iPhone9_4, .iPad7_5, .iPad7_6, .iPod9_1, .iPad7_11, .iPad7_12:
731 | return "Apple A10 Fusion"
732 | /// iPad Pro (2nd)
733 | case .iPad7_1, .iPad7_2, .iPad7_3, .iPad7_4:
734 | return "Apple A10X Fusion"
735 | /// iPhone 8/8 Plus, iPhone X
736 | case .iPhone10_1, .iPhone10_2, .iPhone10_3, .iPhone10_4, .iPhone10_5, .iPhone10_6:
737 | return "Apple A11 Bionic"
738 | /// iPhone XS/XS Max, iPhone XR, iPad Air (3rd), iPad mini (5th), iPad (8th)
739 | case .iPhone11_2, .iPhone11_4, .iPhone11_6, .iPhone11_8, .iPad11_3, .iPad11_4, .iPad11_1, .iPad11_2, .iPad11_6, .iPad11_7:
740 | return "Apple A12 Bionic"
741 | /// iPad Pro (3rd)
742 | case .iPad8_1, .iPad8_2, .iPad8_3, .iPad8_4, .iPad8_5, .iPad8_6, .iPad8_7, .iPad8_8:
743 | return "Apple A12X Bionic"
744 | /// iPad Pro (4th)
745 | case .iPad8_9, .iPad8_10, .iPad8_11, .iPad8_12:
746 | return "Apple A12Z Bionic"
747 | /// iPhone 11, iPhone 11 Pro/11 Pro Max, iPhone SE (2nd), iPad (9th)
748 | case .iPhone12_1, .iPhone12_3, .iPhone12_5, .iPhone12_8, .iPad12_2, .iPad12_1:
749 | return "Apple A13 Bionic"
750 | /// iPhone 12/12 mini, iPhone 12 Pro/12 Pro Max, iPad Air (4th), iPad (10th)
751 | case .iPhone13_1, .iPhone13_2, .iPhone13_3, .iPhone13_4, .iPad13_1, .iPad13_2, .iPad13_18, .iPad13_19:
752 | return "Apple A14 Bionic"
753 | /// iPad Pro (5th), iPad Air (5th)
754 | case .iPad13_4, .iPad13_5, .iPad13_6, .iPad13_7, .iPad13_8, .iPad13_9, .iPad13_10, .iPad13_11, .iPad13_16, .iPad13_17:
755 | return "Apple M1"
756 | /// iPhone 13/13 mini, iPhone 13 Pro/13 Pro Max, iPad mini (6th), iPhone SE (3rd), iPhone 14/14 Plus
757 | case .iPhone14_4, .iPhone14_5, .iPhone14_2, .iPhone14_3, .iPad14_2, .iPad14_1, .iPhone14_6, .iPhone14_7, .iPhone14_8:
758 | return "Apple A15 Bionic"
759 | /// iPhone 14 Pro/14 Pro Max, iPhone 15/15 Plus
760 | case .iPhone15_2, .iPhone15_3, .iPhone15_4, .iPhone15_5:
761 | return "Apple A16 Bionic"
762 | /// iPad Pro (6th)
763 | case .iPad14_3_A, .iPad14_3_B, .iPad14_4_A, .iPad14_4_B, .iPad14_5_A, .iPad14_5_B, .iPad14_6_A, .iPad14_6_B, .iPad14_8, .iPad14_9, .iPad14_10, .iPad14_11:
764 | return "Apple M2"
765 | /// iPhone 15 Pro/15 Pro Max
766 | case .iPhone16_1, .iPhone16_2, .iPad16_1, .iPad16_2:
767 | return "Apple A17 Pro"
768 | /// iPad Pro (M4)
769 | case .iPad16_3, .iPad16_4, .iPad16_5, .iPad16_6:
770 | return "Apple M4"
771 | /// iPhone 16/16 Plus
772 | case .iPhone17_3, .iPhone17_4, .iPhone17_5:
773 | return "Apple A18"
774 | /// iPhone 16 Pro/16 Pro Max
775 | case .iPhone17_1, .iPhone17_2:
776 | return "Apple A18 Pro"
777 | /// iPhone 17
778 | case .iPhone18_3:
779 | return "Apple A19"
780 | /// iPhone 17 Pro/17 Pro Max, iPhone Aie
781 | case .iPhone18_4, .iPhone18_2, .iPhone18_1:
782 | return "Apple A19 Pro"
783 | /// iPad Pro (M5)
784 | case .iPad17_1, .iPad17_2, .iPad17_3, .iPad17_4:
785 | return "Apple M5"
786 | }
787 | }
788 |
789 |
790 | // CPU Information
791 | func cpu() -> String {
792 | switch self {
793 | /// Simulator
794 | case .i386, .x86_64, .arm64:
795 | return "N/A"
796 | /// iPhone, iPod touch (1st), iPhone 3G
797 | case .iPod1_1, .iPhone1_1, .iPhone1_2:
798 | return "412MHz 1-core"
799 | /// iPod touch (2nd)
800 | case .iPod2_1:
801 | return "533MHz 1-core"
802 | /// iPhone 3GS
803 | case .iPhone2_1:
804 | return "600MHz 1-core"
805 | /// iPod touch (3rd)
806 | case .iPod3_1:
807 | return "800MHz 1-core"
808 | /// iPhone 4, iPad (1st), iPod touch (4th)
809 | /// Apple A4
810 | case .iPod4_1, .iPhone3_1, .iPhone3_2, .iPhone3_3, .iPad1_1:
811 | return "1.0GHz 1-core"
812 | /// iPhone 4s, iPad 2, iPod touch (5th), iPad mini (1st)
813 | /// Apple A5
814 | case .iPhone4_1, .iPod5_1, .iPad2_5, .iPad2_6, .iPad2_7, .iPad2_1, .iPad2_2, .iPad2_3, .iPad2_4:
815 | return "1.0GHz 2-core"
816 | /// iPad (3rd)
817 | /// Apple A5X
818 | case .iPad3_1, .iPad3_2, .iPad3_3:
819 | return "1.0GHz 2-core"
820 | /// iPhone 5, iPhone 5c
821 | /// Apple A6
822 | case .iPhone5_1, .iPhone5_2, .iPhone5_3, .iPhone5_4:
823 | return "1.3GHz 2-core"
824 | /// iPad (4th)
825 | /// Apple A6X
826 | case .iPad3_4, .iPad3_5, .iPad3_6:
827 | return "1.4GHz 2-core"
828 | /// iPhone 5s, iPad mini 2, iPad mini 3
829 | /// Apple A7
830 | case .iPhone6_1, .iPhone6_2, .iPad4_4, .iPad4_5, .iPad4_6, .iPad4_7, .iPad4_8, .iPad4_9:
831 | return "1.3GHz 2-core"
832 | /// iPad Air (1st)
833 | /// Apple A7
834 | case .iPad4_1, .iPad4_2, .iPad4_3:
835 | return "1.4GHz 2-core"
836 | /// iPhone 6/6 Plus, iPod touch (6th), iPad mini 4
837 | /// Apple A8
838 | case .iPhone7_1, .iPhone7_2, .iPod7_1, .iPad5_1, .iPad5_2:
839 | return "1.5GHz 2-core"
840 | /// iPad Air (2nd)
841 | /// Apple A8
842 | case .iPad5_4, .iPad5_3:
843 | return "1.5GHz 3-core"
844 | /// iPhone 6s/6s Plus, iPhone SE (1st), iPad (5th)
845 | /// Apple A9
846 | case .iPhone8_1, .iPhone8_2, .iPhone8_4, .iPad6_11, .iPad6_12:
847 | return "1.85GHz 2-core"
848 | /// iPad Pro (1st)
849 | /// Apple A9X
850 | case .iPad6_3, .iPad6_4, .iPad6_7, .iPad6_8:
851 | return "2.26GHz 2-core"
852 | /// iPhone 7/7 Plus, iPad (6th), iPod touch (7th), iPad (7th)
853 | /// Apple A10 Fusion
854 | case .iPhone9_1, .iPhone9_2, .iPhone9_3, .iPhone9_4, .iPad7_5, .iPad7_6, .iPod9_1, .iPad7_11, .iPad7_12:
855 | return "2.34GHz 4-core"
856 | /// iPad Pro (2nd)
857 | /// Apple A10X Fusion
858 | case .iPad7_1, .iPad7_2, .iPad7_3, .iPad7_4:
859 | return "2.36GHz 6-core"
860 | /// iPhone 8/8 Plus, iPhone X
861 | /// Apple A11 Bionic
862 | case .iPhone10_1, .iPhone10_2, .iPhone10_3, .iPhone10_4, .iPhone10_5, .iPhone10_6:
863 | return "2.39GHz 6-core"
864 | /// iPhone XS/XS Max, iPhone XR, iPad Air (3rd), iPad mini (5th), iPad (8th)
865 | /// Apple A12 Bionic
866 | case .iPhone11_2, .iPhone11_4, .iPhone11_6, .iPhone11_8, .iPad11_3, .iPad11_4, .iPad11_1, .iPad11_2, .iPad11_6, .iPad11_7:
867 | return "2.49 GHz 6-core"
868 | /// iPad Pro (3rd), iPad Pro (4th)
869 | /// Apple A12X/A12Z Bionic
870 | case .iPad8_1, .iPad8_2, .iPad8_3, .iPad8_4, .iPad8_5, .iPad8_6, .iPad8_7, .iPad8_8, .iPad8_9, .iPad8_10, .iPad8_11, .iPad8_12:
871 | return "2.49GHz 8-core"
872 | /// iPhone 11, iPhone 11 Pro/11 Pro Max, iPhone SE (2nd), iPad (9th)
873 | /// Apple A13 Bionic
874 | case .iPhone12_1, .iPhone12_3, .iPhone12_5, .iPhone12_8, .iPad12_2, .iPad12_1:
875 | return "2.65GHz 6-core"
876 | /// iPhone 12/12 mini, iPhone 12 Pro/12 Pro Max, iPad Air (4th), iPad (10th)
877 | /// Apple A14 Bionic
878 | case .iPhone13_1, .iPhone13_2, .iPhone13_3, .iPhone13_4, .iPad13_1, .iPad13_2, .iPad13_18, .iPad13_19:
879 | return "2.99GHz 6-core"
880 | /// iPad Pro (5th), iPad Air (5th)
881 | /// Apple M1
882 | case .iPad13_4, .iPad13_5, .iPad13_6, .iPad13_7, .iPad13_8, .iPad13_9, .iPad13_10, .iPad13_11, .iPad13_16, .iPad13_17:
883 | return "3.2GHz 8-core"
884 | /// iPhone 13/13 mini, iPhone 13 Pro/13 Pro Max, iPhone SE (3rd), iPhone 14/14 Plus
885 | /// Apple A15 Bionic
886 | case .iPhone14_4, .iPhone14_5, .iPhone14_2, .iPhone14_3, .iPhone14_6, .iPhone14_7, .iPhone14_8:
887 | return "3.23GHz 6-core"
888 | /// iPad mini (6th)
889 | /// Apple A15 Bionic
890 | case .iPad14_2, .iPad14_1:
891 | return "2.93GHz 6-core"
892 | /// iPhone 14 Pro/14 Pro Max, iPhone 15/15 Plus
893 | /// Apple A16 Bionic
894 | case .iPhone15_2, .iPhone15_3, .iPhone15_4, .iPhone15_5:
895 | return "3.46GHz 6-core"
896 | /// iPad Pro (6th)
897 | /// Apple M2
898 | case .iPad14_3_A, .iPad14_3_B, .iPad14_4_A, .iPad14_4_B, .iPad14_5_A, .iPad14_5_B, .iPad14_6_A, .iPad14_6_B, .iPad14_8, .iPad14_9, .iPad14_10, .iPad14_11:
899 | return "3.49GHz 6-core"
900 | /// iPhone 15 Pro/15 Pro Max
901 | /// Apple A17 Pro
902 | case .iPhone16_1, .iPhone16_2, .iPad16_1, .iPad16_2:
903 | return "3.78GHz 6-core"
904 | /// iPad Pro M4
905 | /// Apple M4
906 | case .iPad16_3, .iPad16_4, .iPad16_5, .iPad16_6:
907 | return "4.4GHz 10-core"
908 | /// iPhone 16/16Plus, iPhone 16Pro/16 Pro Max
909 | /// Apple A18, Apple A18 Pro
910 | case .iPhone17_1, .iPhone17_2, .iPhone17_3, .iPhone17_4, .iPhone17_5:
911 | return "4.05GHz 6-core"
912 | /// iPhone 17, iPhone 17 Pro/17 Pro Max, iPhone Air
913 | /// Apple A19, Apple A19 Pro
914 | case .iPhone18_1, .iPhone18_2, .iPhone18_3, .iPhone18_4:
915 | return "4.26GHz 6-core"
916 | /// iPad Pro (M5)
917 | case .iPad17_1, .iPad17_2, .iPad17_3, .iPad17_4:
918 | return "4.43GHz 10-core"
919 | }
920 | }
921 |
922 | // GPU Information
923 | func gpu() -> String {
924 | switch self {
925 | /// Simulator
926 | case .i386, .x86_64, .arm64:
927 | return "N/A"
928 | /// iPhone, iPod touch (1st), iPhone 3G
929 | case .iPod1_1, .iPhone1_1, .iPhone1_2:
930 | return "PowerVR MBX Lite"
931 | /// iPod touch (2nd)
932 | case .iPod2_1:
933 | return "PowerVR MBX Lite"
934 | /// iPhone 3GS
935 | case .iPhone2_1:
936 | return "PowerVR SGX535"
937 | /// iPod touch (3rd)
938 | case .iPod3_1:
939 | return "PowerVR SGX535"
940 | /// iPhone 4, iPad (1st), iPod touch (4th)
941 | case .iPod4_1, .iPhone3_1, .iPhone3_2, .iPhone3_3, .iPad1_1:
942 | return "PowerVR SGX535"
943 | /// iPhone 4s, iPad 2, iPod touch (5th), iPad mini (1st)
944 | case .iPhone4_1, .iPod5_1, .iPad2_5, .iPad2_6, .iPad2_7, .iPad2_1, .iPad2_2, .iPad2_3, .iPad2_4:
945 | return "PowerVR SGX543MP2 2-core"
946 | /// iPad (3rd)
947 | case .iPad3_1, .iPad3_2, .iPad3_3:
948 | return "PowerVR SGX554MP4 4-core"
949 | /// iPhone 5, iPhone 5c
950 | case .iPhone5_1, .iPhone5_2, .iPhone5_3, .iPhone5_4:
951 | return "PowerVR SGX543MP3 3-core"
952 | /// iPad (4th)
953 | case .iPad3_4, .iPad3_5, .iPad3_6:
954 | return "PowerVR SGX554MP4 4-core"
955 | /// iPhone 5s, iPad mini 2, iPad mini 3, iPad Air (1st)
956 | case .iPhone6_1, .iPhone6_2, .iPad4_4, .iPad4_5, .iPad4_6, .iPad4_7, .iPad4_8, .iPad4_9, .iPad4_1, .iPad4_2, .iPad4_3:
957 | return "PowerVR G6430 4-core"
958 | /// iPhone 6/6 Plus, iPod touch (6th), iPad mini 4
959 | case .iPhone7_1, .iPhone7_2, .iPod7_1, .iPad5_1, .iPad5_2:
960 | return "PowerVR GXA6450 4-core"
961 | /// iPad Air (2nd)
962 | case .iPad5_4, .iPad5_3:
963 | return "PowerVR GXA6850 8-core"
964 | /// iPhone 6s/6s Plus, iPhone SE (1st), iPad (5th)
965 | case .iPhone8_1, .iPhone8_2, .iPhone8_4, .iPad6_11, .iPad6_12:
966 | return "PowerVR GT7600 6-core"
967 | /// iPad Pro (1st)
968 | case .iPad6_3, .iPad6_4, .iPad6_7, .iPad6_8:
969 | return "PowerVR GTA7850 12-core"
970 | /// iPhone 7/7 Plus, iPad (6th), iPod touch (7th), iPad (7th)
971 | case .iPhone9_1, .iPhone9_2, .iPhone9_3, .iPhone9_4, .iPad7_5, .iPad7_6, .iPod9_1, .iPad7_11, .iPad7_12:
972 | return "PowerVR GT7600 Plus 6-core"
973 | /// iPad Pro (2nd)
974 | case .iPad7_1, .iPad7_2, .iPad7_3, .iPad7_4:
975 | return "PowerVR GT7600 Plus 12-core"
976 | /// iPhone 8/8 Plus, iPhone X
977 | /// Apple A11 Bionic
978 | case .iPhone10_1, .iPhone10_2, .iPhone10_3, .iPhone10_4, .iPhone10_5, .iPhone10_6:
979 | return "3-core"
980 | /// iPhone XS/XS Max, iPhone XR, iPad Air (3rd), iPad mini (5th), iPad (8th)
981 | /// Apple A12 Bionic
982 | case .iPhone11_2, .iPhone11_4, .iPhone11_6, .iPhone11_8, .iPad11_3, .iPad11_4, .iPad11_1, .iPad11_2, .iPad11_6, .iPad11_7:
983 | return "4-core"
984 | /// iPad Pro (3rd)
985 | /// Apple A12X Bionic
986 | case .iPad8_1, .iPad8_2, .iPad8_3, .iPad8_4, .iPad8_5, .iPad8_6, .iPad8_7, .iPad8_8:
987 | return "7-core"
988 | /// iPad Pro (4th)
989 | /// Apple A12Z Bionic
990 | case .iPad8_9, .iPad8_10, .iPad8_11, .iPad8_12:
991 | return "8-core"
992 | /// iPhone 11, iPhone 11 Pro/11 Pro Max, iPhone SE (2nd), iPad (9th)
993 | /// Apple A13 Bionic
994 | case .iPhone12_1, .iPhone12_3, .iPhone12_5, .iPhone12_8, .iPad12_2, .iPad12_1:
995 | return "4-core"
996 | /// iPhone 12/12 mini, iPhone 12 Pro/12 Pro Max, iPad Air (4th), iPad (10th)
997 | /// Apple A14 Bionic
998 | case .iPhone13_1, .iPhone13_2, .iPhone13_3, .iPhone13_4, .iPad13_1, .iPad13_2, .iPad13_18, .iPad13_19:
999 | return "4-core"
1000 | /// iPad Pro (5th), iPad Air (5th)
1001 | /// Apple M1
1002 | case .iPad13_4, .iPad13_5, .iPad13_6, .iPad13_7, .iPad13_8, .iPad13_9, .iPad13_10, .iPad13_11, .iPad13_16, .iPad13_17:
1003 | return "8-core"
1004 | /// iPhone 13 Pro/13 Pro Max, iPad mini (6th), iPhone 14/14 Plus
1005 | /// Apple A15 Bionic
1006 | case .iPhone14_2, .iPhone14_3, .iPad14_2, .iPad14_1, .iPhone14_7, .iPhone14_8:
1007 | return "5-core"
1008 | /// iPhone 13/13 mini, iPhone SE (3rd)
1009 | /// Apple A15 Bionic
1010 | case .iPhone14_4, .iPhone14_5, .iPhone14_6:
1011 | return "4-core"
1012 | /// iPhone 14 Pro/14 Pro Max, iPhone 15/15 Plus
1013 | /// Apple A15 Bionic
1014 | case .iPhone15_2, .iPhone15_3, .iPhone15_4, .iPhone15_5:
1015 | return "5-core"
1016 | /// iPad Pro (6th)
1017 | /// Apple M2
1018 | case .iPad14_3_A, .iPad14_3_B, .iPad14_4_A, .iPad14_4_B, .iPad14_5_A, .iPad14_5_B, .iPad14_6_A, .iPad14_6_B, .iPad14_8, .iPad14_9, .iPad14_10, .iPad14_11:
1019 | return "10-core"
1020 | /// iPhone 15 Pro/15 Pro Max
1021 | /// Apple A17 Pro
1022 | case .iPhone16_1, .iPhone16_2, .iPad16_1, .iPad16_2:
1023 | return "6-core"
1024 | /// iPad Pro M4
1025 | /// Apple M4
1026 | case .iPad16_3, .iPad16_4, .iPad16_5, .iPad16_6:
1027 | return "10-core"
1028 | /// iPhone 16/16 Plus
1029 | /// Apple A18
1030 | case .iPhone17_3, .iPhone17_4:
1031 | return "5-core"
1032 | /// iPhone 16Pro/16 Pro Max
1033 | /// Apple A18 Pro
1034 | case .iPhone17_1, .iPhone17_2:
1035 | return "6-core"
1036 | /// iPhone 16e
1037 | /// Apple A18
1038 | case .iPhone17_5:
1039 | return "4-core"
1040 | /// iPhone 17
1041 | /// Apple A19
1042 | case .iPhone18_3:
1043 | return "5-core"
1044 | /// iPhone Air
1045 | /// Apple A19 Pro
1046 | case .iPhone18_4:
1047 | return "5-core"
1048 | /// iPhone 17 Pro/17 Pro Max
1049 | /// Apple A19 Pro
1050 | case .iPhone18_1, .iPhone18_2:
1051 | return "6-core"
1052 | /// iPad Pro (M5)
1053 | case .iPad17_1, .iPad17_2, .iPad17_3, .iPad17_4:
1054 | return "10-core"
1055 | }
1056 | }
1057 |
1058 | // Neural Engine Information
1059 | func neuralEngine() -> String {
1060 | switch self {
1061 | /// Simulator
1062 | case .i386, .x86_64, .arm64:
1063 | return "N/A"
1064 | /// Apple A11 Bionic
1065 | case .iPhone10_1, .iPhone10_2, .iPhone10_3, .iPhone10_4, .iPhone10_5, .iPhone10_6:
1066 | return "2-core"
1067 | /// iPhone XS/XS Max, iPhone XR, iPad Air (3rd), iPad mini (5th), iPad (8th)
1068 | /// Apple A12 Bionic
1069 | case .iPhone11_2, .iPhone11_4, .iPhone11_6, .iPhone11_8, .iPad11_3, .iPad11_4, .iPad11_1, .iPad11_2, .iPad11_6, .iPad11_7:
1070 | return "8-core"
1071 | /// iPad Pro (3rd), iPad Pro (4th)
1072 | /// Apple A12X/A12Z Bionic
1073 | case .iPad8_1, .iPad8_2, .iPad8_3, .iPad8_4, .iPad8_5, .iPad8_6, .iPad8_7, .iPad8_8, .iPad8_9, .iPad8_10, .iPad8_11, .iPad8_12:
1074 | return "8-core"
1075 | /// iPhone 11, iPhone 11 Pro/11 Pro Max, iPhone SE (2nd), iPad (6th)
1076 | /// Apple A13 Bionic
1077 | case .iPhone12_1, .iPhone12_3, .iPhone12_5, .iPhone12_8, .iPad12_2, .iPad12_1:
1078 | return "8-core"
1079 | /// iPhone 12/12 mini, iPhone 12 Pro/12 Pro Max, iPad Air (4th), iPad (10th)
1080 | /// Apple A14 Bionic
1081 | /// 11 TOPS
1082 | case .iPhone13_1, .iPhone13_2, .iPhone13_3, .iPhone13_4, .iPad13_1, .iPad13_2, .iPad13_18, .iPad13_19:
1083 | return "16-core"
1084 | /// iPad Pro (5th), iPad Air (3rd)
1085 | /// Apple M1
1086 | /// 11 TOPS
1087 | case .iPad13_4, .iPad13_5, .iPad13_6, .iPad13_7, .iPad13_8, .iPad13_9, .iPad13_10, .iPad13_11, .iPad13_16, .iPad13_17:
1088 | return "16-core"
1089 | /// iPhone 13/13 mini, iPhone 13 Pro/13 Pro Max, iPad mini (6th), iPhone SE (3rd)
1090 | /// Apple A15 Bionic
1091 | /// 15.8 TOPS
1092 | case .iPhone14_4, .iPhone14_5, .iPhone14_2, .iPhone14_3, .iPad14_2, .iPad14_1, .iPhone14_6, .iPhone14_7, .iPhone14_8:
1093 | return "16-core"
1094 | /// iPhone 14 Pro/14 Pro Max, iPhone 15/15 Plus
1095 | /// Apple A16 Bionic
1096 | /// 17 TOPS
1097 | case .iPhone15_2, .iPhone15_3, .iPhone15_4, .iPhone15_5:
1098 | return "16-core"
1099 | /// iPad Pro (6th)
1100 | /// Apple M2
1101 | /// 15.8 TOPS
1102 | case .iPad14_3_A, .iPad14_3_B, .iPad14_4_A, .iPad14_4_B, .iPad14_5_A, .iPad14_5_B, .iPad14_6_A, .iPad14_6_B, .iPad14_8, .iPad14_9, .iPad14_10, .iPad14_11:
1103 | return "16-core"
1104 | /// iPhone 15 Pro/15 Pro Max
1105 | /// Apple A17 Pro
1106 | /// 35 TOPS
1107 | case .iPhone16_1, .iPhone16_2, .iPad16_1, .iPad16_2:
1108 | return "16-core"
1109 | /// iPad Pro M4
1110 | /// Apple M4
1111 | /// 38 TOPS
1112 | case .iPad16_3, .iPad16_4, .iPad16_5, .iPad16_6:
1113 | return "16-core"
1114 | /// iPhone 16/16 Plus, iPhone 16 Pro/16 Pro Max
1115 | /// Apple A18, Apple A18 Pro
1116 | /// 35 TOPS
1117 | case .iPhone17_1, .iPhone17_2, .iPhone17_3, .iPhone17_4, .iPhone17_5:
1118 | return "16-core"
1119 | /// iPhone 17, iPhone 17 Pro/17 Pro Max, iPhone Air
1120 | /// Apple A19, Apple A19 Pro
1121 | case .iPhone18_1, .iPhone18_2, .iPhone18_3, .iPhone18_4:
1122 | return "16-core"
1123 | /// iPad Pro (M5)
1124 | case .iPad17_1, .iPad17_2, .iPad17_3, .iPad17_4:
1125 | return "16-core"
1126 | /// Other device
1127 | default:
1128 | return "None"
1129 | }
1130 | }
1131 |
1132 | // TODO: Add devices when new iPhone with the Dynamic Island is announced.
1133 | // Dynamic Island
1134 | func hasDynamicIsland() -> Bool {
1135 | switch self {
1136 | // 14 Pro/Pro Max, 15/15 Plus, 15 Pro/Pro Max, 16/16 Plus, 16 Pro/16 Pro Max, 17, 17 Pro/17 Pro Max, Air
1137 | case .iPhone15_2, .iPhone15_3, .iPhone15_4, .iPhone15_5,
1138 | .iPhone16_1, .iPhone16_2,
1139 | .iPhone17_1, .iPhone17_2, .iPhone17_3, .iPhone17_4,
1140 | .iPhone18_1, .iPhone18_2, .iPhone18_3, .iPhone18_4:
1141 | return true
1142 | default:
1143 | return false
1144 | }
1145 | }
1146 | }
1147 | }
1148 |
--------------------------------------------------------------------------------