mirror of
https://github.com/devicekit/DeviceKit.git
synced 2026-05-17 10:20:34 +00:00
3d2a7bd32e
* fix m5 iPad Pro models * Add changelog entry for PR 480. --------- Co-authored-by: Zandor Smith <info@zsinfo.nl>
1644 lines
106 KiB
Plaintext
1644 lines
106 KiB
Plaintext
//===----------------------------------------------------------------------===//
|
||
//
|
||
// This source file is part of the DeviceKit open source project
|
||
//
|
||
// Copyright © 2014 - 2018 Dennis Weissmann and the DeviceKit project authors
|
||
//
|
||
// License: https://github.com/dennisweissmann/DeviceKit/blob/master/LICENSE
|
||
// Contributors: https://github.com/dennisweissmann/DeviceKit#contributors
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
%{
|
||
class Device:
|
||
def __init__(self, caseName, comment, imageURL, identifiers, diagonal, screenRatio, description, safeDescription, ppi, isPlusFormFactor, isPadMiniFormFactor, isPro, isXSeries, hasTouchID, hasFaceID, hasSensorHousing, supportsWirelessCharging, hasRoundedDisplayCorners, hasDynamicIsland, applePencilSupport, hasForce3dTouchSupport, cameras, hasLidarSensor, cpu, hasUSBCConnectivity, has5gSupport):
|
||
self.caseName = caseName
|
||
self.comment = comment
|
||
self.imageURL = imageURL
|
||
self.identifiers = identifiers
|
||
self.diagonal = diagonal
|
||
self.screenRatio = screenRatio
|
||
self.description = description
|
||
self.safeDescription = safeDescription
|
||
self.ppi = ppi
|
||
self.isPlusFormFactor = isPlusFormFactor
|
||
self.isPadMiniFormFactor = isPadMiniFormFactor
|
||
self.isPro = isPro
|
||
self.isXSeries = isXSeries
|
||
self.hasTouchID = hasTouchID
|
||
self.hasFaceID = hasFaceID
|
||
self.hasSensorHousing = hasSensorHousing
|
||
self.supportsWirelessCharging = supportsWirelessCharging
|
||
self.hasRoundedDisplayCorners = hasRoundedDisplayCorners
|
||
self.hasDynamicIsland = hasDynamicIsland
|
||
self.applePencilSupport = applePencilSupport
|
||
self.hasForce3dTouchSupport = hasForce3dTouchSupport
|
||
self.cameras = cameras
|
||
self.hasLidarSensor = hasLidarSensor
|
||
self.cpu = cpu
|
||
self.hasUSBCConnectivity = hasUSBCConnectivity
|
||
self.has5gSupport = has5gSupport
|
||
|
||
# iOS
|
||
iPods = [
|
||
Device("iPodTouch5", "Device is an [iPod touch (5th generation)](https://support.apple.com/kb/SP657)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP657/sp657_ipod-touch_size.jpg", ["iPod5,1"], 4, (9, 16), "iPod touch (5th generation)", "iPod touch (5th generation)", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a5", False, False),
|
||
Device("iPodTouch6", "Device is an [iPod touch (6th generation)](https://support.apple.com/kb/SP720)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP720/SP720-ipod-touch-specs-color-sg-2015.jpg", ["iPod7,1"], 4, (9, 16), "iPod touch (6th generation)", "iPod touch (6th generation)", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a8", False, False),
|
||
Device("iPodTouch7", "Device is an [iPod touch (7th generation)](https://support.apple.com/kb/SP796)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP796/ipod-touch-7th-gen_2x.png", ["iPod9,1"], 4, (9, 16), "iPod touch (7th generation)", "iPod touch (7th generation)", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a10Fusion", False, False),
|
||
]
|
||
|
||
iPhones = [
|
||
Device("iPhone4", "Device is an [iPhone 4](https://support.apple.com/kb/SP587)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg", ["iPhone3,1", "iPhone3,2", "iPhone3,3"], 3.5, (2, 3), "iPhone 4", "iPhone 4", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a4", False, False),
|
||
Device("iPhone4s", "Device is an [iPhone 4s](https://support.apple.com/kb/SP643)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg", ["iPhone4,1"], 3.5, (2, 3), "iPhone 4s", "iPhone 4s", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a5", False, False),
|
||
Device("iPhone5", "Device is an [iPhone 5](https://support.apple.com/kb/SP655)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP655/sp655_iphone5_color.jpg", ["iPhone5,1", "iPhone5,2"], 4, (9, 16), "iPhone 5", "iPhone 5", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a6", False, False),
|
||
Device("iPhone5c", "Device is an [iPhone 5c](https://support.apple.com/kb/SP684)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP684/SP684-color_yellow.jpg", ["iPhone5,3", "iPhone5,4"], 4, (9, 16), "iPhone 5c", "iPhone 5c", 326, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a6", False, False),
|
||
Device("iPhone5s", "Device is an [iPhone 5s](https://support.apple.com/kb/SP685)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP685/SP685-color_black.jpg", ["iPhone6,1", "iPhone6,2"], 4, (9, 16), "iPhone 5s", "iPhone 5s", 326, False, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a7", False, False),
|
||
Device("iPhone6", "Device is an [iPhone 6](https://support.apple.com/kb/SP705)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP705/SP705-iphone_6-mul.png", ["iPhone7,2"], 4.7, (9, 16), "iPhone 6", "iPhone 6", 326, False, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a8", False, False),
|
||
Device("iPhone6Plus", "Device is an [iPhone 6 Plus](https://support.apple.com/kb/SP706)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP706/SP706-iphone_6_plus-mul.png", ["iPhone7,1"], 5.5, (9, 16), "iPhone 6 Plus", "iPhone 6 Plus", 401, True, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a8", False, False),
|
||
Device("iPhone6s", "Device is an [iPhone 6s](https://support.apple.com/kb/SP726)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP726/SP726-iphone6s-gray-select-2015.png", ["iPhone8,1"], 4.7, (9, 16), "iPhone 6s", "iPhone 6s", 326, False, False, False, False, True, False, False, False, False, False, 0, True, 1, False, "a9", False, False),
|
||
Device("iPhone6sPlus", "Device is an [iPhone 6s Plus](https://support.apple.com/kb/SP727)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP727/SP727-iphone6s-plus-gray-select-2015.png", ["iPhone8,2"], 5.5, (9, 16), "iPhone 6s Plus", "iPhone 6s Plus", 401, True, False, False, False, True, False, False, False, False, False, 0, True, 1, False, "a9", False, False),
|
||
Device("iPhone7", "Device is an [iPhone 7](https://support.apple.com/kb/SP743)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP743/iphone7-black.png", ["iPhone9,1", "iPhone9,3"], 4.7, (9, 16), "iPhone 7", "iPhone 7", 326, False, False, False, False, True, False, False, False, False, False, 0, True, 1, False, "a10Fusion", False, False),
|
||
Device("iPhone7Plus", "Device is an [iPhone 7 Plus](https://support.apple.com/kb/SP744)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP744/iphone7-plus-black.png", ["iPhone9,2", "iPhone9,4"], 5.5, (9, 16), "iPhone 7 Plus", "iPhone 7 Plus", 401, True, False, False, False, True, False, False, False, False, False, 0, True, 12, False, "a10Fusion", False, False),
|
||
Device("iPhoneSE", "Device is an [iPhone SE](https://support.apple.com/kb/SP738)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP738/SP738.png", ["iPhone8,4"], 4, (9, 16), "iPhone SE", "iPhone SE", 326, False, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a9", False, False),
|
||
Device("iPhone8", "Device is an [iPhone 8](https://support.apple.com/kb/SP767)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP767/iphone8.png", ["iPhone10,1", "iPhone10,4"], 4.7, (9, 16), "iPhone 8", "iPhone 8", 326, False, False, False, False, True, False, False, True, False, False, 0, True, 1, False, "a11Bionic", False, False),
|
||
Device("iPhone8Plus", "Device is an [iPhone 8 Plus](https://support.apple.com/kb/SP768)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP768/iphone8plus.png", ["iPhone10,2", "iPhone10,5"], 5.5, (9, 16), "iPhone 8 Plus", "iPhone 8 Plus", 401, True, False, False, False, True, False, False, True, False, False, 0, True, 12, False, "a11Bionic", False, False),
|
||
Device("iPhoneX", "Device is an [iPhone X](https://support.apple.com/kb/SP770)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP770/iphonex.png", ["iPhone10,3", "iPhone10,6"], 5.8, (9, 19.5), "iPhone X", "iPhone X", 458, False, False, False, True, False, True, True, True, True, False, 0, True, 12, False, "a11Bionic", False, False),
|
||
Device("iPhoneXS", "Device is an [iPhone Xs](https://support.apple.com/kb/SP779)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP779/SP779-iphone-xs.jpg", ["iPhone11,2"], 5.8, (9, 19.5), "iPhone Xs", "iPhone XS", 458, False, False, False, True, False, True, True, True, True, False, 0, True, 12, False, "a12Bionic", False, False),
|
||
Device("iPhoneXSMax", "Device is an [iPhone Xs Max](https://support.apple.com/kb/SP780)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP780/SP780-iPhone-Xs-Max.jpg", ["iPhone11,4", "iPhone11,6"], 6.5, (9, 19.5), "iPhone Xs Max", "iPhone XS Max", 458, True, False, False, True, False, True, True, True, True, False, 0, True, 12, False, "a12Bionic", False, False),
|
||
Device("iPhoneXR", "Device is an [iPhone Xʀ](https://support.apple.com/kb/SP781)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP781/SP781-iPhone-xr.jpg", ["iPhone11,8"], 6.1, (9, 19.5), "iPhone Xʀ", "iPhone XR", 326, False, False, False, True, False, True, True, True, True, False, 0, False, 1, False, "a12Bionic", False, False),
|
||
Device("iPhone11", "Device is an [iPhone 11](https://support.apple.com/kb/SP804)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP804/sp804-iphone11_2x.png", ["iPhone12,1"], 6.1, (9, 19.5), "iPhone 11", "iPhone 11", 326, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a13Bionic", False, False),
|
||
Device("iPhone11Pro", "Device is an [iPhone 11 Pro](https://support.apple.com/kb/SP805)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP805/sp805-iphone11pro_2x.png", ["iPhone12,3"], 5.8, (9, 19.5), "iPhone 11 Pro", "iPhone 11 Pro", 458, False, False, True, True, False, True, True, True, True, False, 0, False, 123, False, "a13Bionic", False, False),
|
||
Device("iPhone11ProMax", "Device is an [iPhone 11 Pro Max](https://support.apple.com/kb/SP806)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP806/sp806-iphone11pro-max_2x.png", ["iPhone12,5"], 6.5, (9, 19.5), "iPhone 11 Pro Max", "iPhone 11 Pro Max", 458, True, False, True, True, False, True, True, True, True, False, 0, False, 123, False, "a13Bionic", False, False),
|
||
Device("iPhoneSE2", "Device is an [iPhone SE (2nd generation)](https://support.apple.com/kb/SP820)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP820/iphone-se-2nd-gen_2x.png", ["iPhone12,8"], 4.7, (9, 16), "iPhone SE (2nd generation)", "iPhone SE (2nd generation)", 326, False, False, False, False, True, False, False, True, False, False, 0, False, 1, False, "a13Bionic", False, False),
|
||
Device("iPhone12", "Device is an [iPhone 12](https://support.apple.com/kb/SP830)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP830/sp830-iphone12-ios14_2x.png", ["iPhone13,2"], 6.1, (9, 19.5), "iPhone 12", "iPhone 12", 460, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a14Bionic", False, True),
|
||
Device("iPhone12Mini", "Device is an [iPhone 12 mini](https://support.apple.com/kb/SP829)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP829/sp829-iphone12mini-ios14_2x.png", ["iPhone13,1"], 5.4, (9, 19.5), "iPhone 12 mini", "iPhone 12 mini", 476, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a14Bionic", False, True),
|
||
Device("iPhone12Pro", "Device is an [iPhone 12 Pro](https://support.apple.com/kb/SP831)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP831/iphone12pro-ios14_2x.png", ["iPhone13,3"], 6.1, (9, 19.5), "iPhone 12 Pro", "iPhone 12 Pro", 460, False, False, True, True, False, True, True, True, True, False, 0, False, 123, True, "a14Bionic", False, True),
|
||
Device("iPhone12ProMax", "Device is an [iPhone 12 Pro Max](https://support.apple.com/kb/SP832)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP832/iphone12promax-ios14_2x.png", ["iPhone13,4"], 6.7, (9, 19.5), "iPhone 12 Pro Max", "iPhone 12 Pro Max", 458, True, False, True, True, False, True, True, True, True, False, 0, False, 123, True, "a14Bionic", False, True),
|
||
Device("iPhone13", "Device is an [iPhone 13](https://support.apple.com/kb/SP851)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1092/en_US/iphone-13-240.png", ["iPhone14,5"], 6.1, (9, 19.5), "iPhone 13", "iPhone 13", 460, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a15Bionic", False, True),
|
||
Device("iPhone13Mini", "Device is an [iPhone 13 mini](https://support.apple.com/kb/SP847)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1091/en_US/iphone-13mini-240.png", ["iPhone14,4"], 5.4, (9, 19.5), "iPhone 13 mini", "iPhone 13 mini", 476, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a15Bionic", False, True),
|
||
Device("iPhone13Pro", "Device is an [iPhone 13 Pro](https://support.apple.com/kb/SP852)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1093/en_US/iphone-13pro-240.png", ["iPhone14,2"], 6.1, (9, 19.5), "iPhone 13 Pro", "iPhone 13 Pro", 460, False, False, True, True, False, True, True, True, True, False, 0, False, 123, True, "a15Bionic", False, True),
|
||
Device("iPhone13ProMax", "Device is an [iPhone 13 Pro Max](https://support.apple.com/kb/SP848)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1095/en_US/iphone-13promax-240.png", ["iPhone14,3"], 6.7, (9, 19.5), "iPhone 13 Pro Max", "iPhone 13 Pro Max", 458, True, False, True, True, False, True, True, True, True, False, 0, False, 123, True, "a15Bionic", False, True),
|
||
Device("iPhoneSE3", "Device is an [iPhone SE (3rd generation)](https://support.apple.com/kb/SP867)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1136/en_US/iphone-se-3rd-gen-colors-240.png", ["iPhone14,6"], 4.7, (9, 16), "iPhone SE (3rd generation)", "iPhone SE (3rd generation)", 326, False, False, False, False, True, False, False, True, False, False, 0, False, 1, False, "a15Bionic", False, True),
|
||
Device("iPhone14", "Device is an [iPhone 14](https://support.apple.com/kb/SP873)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP873/iphone-14_1_2x.png", ["iPhone14,7"], 6.1, (9, 19.5), "iPhone 14", "iPhone 14", 460, False, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a15Bionic", False, True),
|
||
Device("iPhone14Plus", "Device is an [iPhone 14 Plus](https://support.apple.com/kb/SP874)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP873/iphone-14_1_2x.png", ["iPhone14,8"], 6.7, (9, 19.5), "iPhone 14 Plus", "iPhone 14 Plus", 458, True, False, False, True, False, True, True, True, True, False, 0, False, 13, False, "a15Bionic", False, True),
|
||
Device("iPhone14Pro", "Device is an [iPhone 14 Pro](https://support.apple.com/kb/SP875)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP875/sp875-sp876-iphone14-pro-promax_2x.png", ["iPhone15,2"], 6.1, (9, 19.5), "iPhone 14 Pro", "iPhone 14 Pro", 460, False, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a16Bionic", False, True),
|
||
Device("iPhone14ProMax", "Device is an [iPhone 14 Pro Max](https://support.apple.com/kb/SP876)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP875/sp875-sp876-iphone14-pro-promax_2x.png", ["iPhone15,3"], 6.7, (9, 19.5), "iPhone 14 Pro Max", "iPhone 14 Pro Max", 458, True, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a16Bionic", False, True),
|
||
Device("iPhone15", "Device is an [iPhone 15](https://support.apple.com/en-us/111831)", "", ["iPhone15,4"], 6.1, (9, 19.5), "iPhone 15", "iPhone 15", 460, False, False, False, True, False, True, True, True, True, True, 0, False, 13, False, "a16Bionic", True, True),
|
||
Device("iPhone15Plus", "Device is an [iPhone 15 Plus](https://support.apple.com/en-us/111830)", "", ["iPhone15,5"], 6.7, (9, 19.5), "iPhone 15 Plus", "iPhone 15 Plus", 460, True, False, False, True, False, True, True, True, True, True, 0, False, 13, False, "a16Bionic", True, True),
|
||
Device("iPhone15Pro", "Device is an [iPhone 15 Pro](https://support.apple.com/en-us/111829)", "", ["iPhone16,1"], 6.1, (9, 19.5), "iPhone 15 Pro", "iPhone 15 Pro", 460, False, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a17Pro", True, True),
|
||
Device("iPhone15ProMax", "Device is an [iPhone 15 Pro Max](https://support.apple.com/en-us/111828)", "", ["iPhone16,2"], 6.7, (9, 19.5), "iPhone 15 Pro Max", "iPhone 15 Pro Max", 460, True, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a17Pro", True, True),
|
||
Device("iPhone16", "Device is an [iPhone 16]()", "", ["iPhone17,3"], 6.1, (9, 19.5), "iPhone 16", "iPhone 16", 460, False, False, False, True, False, True, True, True, True, True, 0, False, 13, False, "a18", True, True),
|
||
Device("iPhone16Plus", "Device is an [iPhone 16 Plus]()", "", ["iPhone17,4"], 6.7, (9, 19.5), "iPhone 16 Plus", "iPhone 16 Plus", 460, True, False, False, True, False, True, True, True, True, True, 0, False, 13, False, "a18", True, True),
|
||
Device("iPhone16Pro", "Device is an [iPhone 16 Pro]()", "", ["iPhone17,1"], 6.3, (9, 19.5), "iPhone 16 Pro", "iPhone 16 Pro", 460, False, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a18Pro", True, True),
|
||
Device("iPhone16ProMax", "Device is an [iPhone 16 Pro Max]()", "", ["iPhone17,2"], 6.9, (9, 19.5), "iPhone 16 Pro Max", "iPhone 16 Pro Max", 460, True, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a18Pro", True, True),
|
||
Device("iPhone16e", "Device is an [iPhone 16e](https://support.apple.com/en-us/122208)", "https://cdsassets.apple.com/live/7WUAS350/images/tech-specs/122208-iphone-16e.png", ["iPhone17,5"], 6.1, (9, 19.5), "iPhone 16e", "iPhone 16e", 460, False, False, False, True, False, True, True, True, True, False, 0, False, 1, False, "a18", True, True),
|
||
Device("iPhone17", "Device is an [iPhone 17]()", "", ["iPhone18,3"], 6.3, (9, 19.5), "iPhone 17", "iPhone 17", 460, False, False, False, True, False, True, True, True, True, True, 0, False, 13, False, "a19", True, True),
|
||
Device("iPhone17Pro", "Device is an [iPhone 17 Pro]()", "", ["iPhone18,1"], 6.3, (9, 19.5), "iPhone 17 Pro", "iPhone 17 Pro", 460, False, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a19Pro", True, True),
|
||
Device("iPhone17ProMax", "Device is an [iPhone 17 Pro Max]()", "", ["iPhone18,2"], 6.9, (9, 19.5), "iPhone 17 Pro Max", "iPhone 17 Pro Max", 460, True, False, True, True, False, True, True, True, True, True, 0, False, 123, True, "a19Pro", True, True),
|
||
Device("iPhoneAir", "Device is an [iPhone Air]()", "", ["iPhone18,4"], 6.5, (9, 19.5), "iPhone Air", "iPhone Air", 460, True, False, False, True, False, True, True, True, True, True, 0, False, 1, False, "a19Pro", True, True),
|
||
Device("iPhone17e", "Device is an [iPhone 17e]()", "", ["iPhone18,5"], 6.1, (9, 19.5), "iPhone 17e", "iPhone 17e", 460, False, False, False, True, False, True, True, True, True, False, 0, False, 1, False, "a19", True, True),
|
||
]
|
||
|
||
iPads = [
|
||
Device("iPad2", "Device is an [iPad 2](https://support.apple.com/kb/SP622)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png", ["iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4"], 9.7, (3, 4), "iPad 2", "iPad 2", 132, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a5", False, False),
|
||
Device("iPad3", "Device is an [iPad (3rd generation)](https://support.apple.com/kb/SP647)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg", ["iPad3,1", "iPad3,2", "iPad3,3"], 9.7, (3, 4), "iPad (3rd generation)", "iPad (3rd generation)", 264, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a5X", False, False),
|
||
Device("iPad4", "Device is an [iPad (4th generation)](https://support.apple.com/kb/SP662)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg", ["iPad3,4", "iPad3,5", "iPad3,6"], 9.7, (3, 4), "iPad (4th generation)", "iPad (4th generation)", 264, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a6X", False, False),
|
||
Device("iPadAir", "Device is an [iPad Air](https://support.apple.com/kb/SP692)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP692/SP692-specs_color-mul.png", ["iPad4,1", "iPad4,2", "iPad4,3"], 9.7, (3, 4), "iPad Air", "iPad Air", 264, False, False, False, False, False, False, False, False, False, False, 0, False, 1, False, "a7", False, False),
|
||
Device("iPadAir2", "Device is an [iPad Air 2](https://support.apple.com/kb/SP708)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP708/SP708-space_gray.jpeg", ["iPad5,3", "iPad5,4"], 9.7, (3, 4), "iPad Air 2", "iPad Air 2", 264, False, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a8X", False, False),
|
||
Device("iPad5", "Device is an [iPad (5th generation)](https://support.apple.com/kb/SP751)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP751/ipad_5th_generation.png", ["iPad6,11", "iPad6,12"], 9.7, (3, 4), "iPad (5th generation)", "iPad (5th generation)", 264, False, False, False, False, True, False, False, False, False, False, 0, False, 1, False, "a9", False, False),
|
||
Device("iPad6", "Device is an [iPad (6th generation)](https://support.apple.com/kb/SP774)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP774/sp774-ipad-6-gen_2x.png", ["iPad7,5", "iPad7,6"], 9.7, (3, 4), "iPad (6th generation)", "iPad (6th generation)", 264, False, False, False, False, True, False, False, False, False, False, 1, False, 1, False, "a10Fusion", False, False),
|
||
Device("iPadAir3", "Device is an [iPad Air (3rd generation)](https://support.apple.com/kb/SP787)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP787/ipad-air-2019.jpg", ["iPad11,3", "iPad11,4"], 10.5, (3, 4), "iPad Air (3rd generation)", "iPad Air (3rd generation)", 264, False, False, False, False, True, False, False, False, False, False, 1, False, 1, False, "a12Bionic", False, False),
|
||
Device("iPad7", "Device is an [iPad (7th generation)](https://support.apple.com/kb/SP807)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP807/sp807-ipad-7th-gen_2x.png", ["iPad7,11", "iPad7,12"], 10.2, (3, 4), "iPad (7th generation)", "iPad (7th generation)", 264, False, False, False, False, True, False, False, False, False, False, 1, False, 1, False, "a10Fusion", False, False),
|
||
Device("iPad8", "Device is an [iPad (8th generation)](https://support.apple.com/kb/SP822)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP822/sp822-ipad-8gen_2x.png", ["iPad11,6", "iPad11,7"], 10.2, (3, 4), "iPad (8th generation)", "iPad (8th generation)", 264, False, False, False, False, True, False, False, False, False, False, 1, False, 1, False, "a12Bionic", False, False),
|
||
Device("iPad9", "Device is an [iPad (9th generation)](https://support.apple.com/kb/SP849)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1096/en_US/ipad-9gen-240.png", ["iPad12,1", "iPad12,2"], 10.2, (3, 4), "iPad (9th generation)", "iPad (9th generation)", 264, False, False, False, False, True, False, False, False, False, False, 1, False, 1, False, "a13Bionic", False, False),
|
||
Device("iPad10", "Device is an [iPad (10th generation)](https://support.apple.com/kb/SP884)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP884/sp884-ipad-10gen-960_2x.png", ["iPad13,18", "iPad13,19"], 10.9, (41, 59), "iPad (10th generation)", "iPad (10th generation)", 264, False, False, False, False, True, False, False, False, True, False, 13, False, 1, False, "a14Bionic", True, True),
|
||
Device("iPadA16", "Device is an [iPad (A16)]()", "", ["iPad15,7", "iPad15,8"], 10.9, (41, 59), "iPad (A16)", "iPad (A16)", 264, False, False, False, False, True, False, False, False, True, False, 13, False, 1, False, "a16Bionic", True, True),
|
||
Device("iPadAir4", "Device is an [iPad Air (4th generation)](https://support.apple.com/kb/SP828)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP828/sp828ipad-air-ipados14-960_2x.png", ["iPad13,1", "iPad13,2"], 10.9, (41, 59), "iPad Air (4th generation)", "iPad Air (4th generation)", 264, False, False, False, False, True, False, False, False, True, False, 23, False, 1, False, "a14Bionic", True, False),
|
||
Device("iPadAir5", "Device is an [iPad Air (5th generation)](https://support.apple.com/kb/SP866)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP866/sp866-ipad-air-5gen_2x.png", ["iPad13,16", "iPad13,17"], 10.9, (41, 59), "iPad Air (5th generation)", "iPad Air (5th generation)", 264, False, False, False, False, True, False, False, False, True, False, 23, False, 1, False, "m1", True, True),
|
||
Device("iPadAir11M2", "Device is an [iPad Air 11-inch (M2)](https://support.apple.com/en-us/119894)", "https://cdsassets.apple.com/content/services/pub/image?productid=301027&size=240x240", ["iPad14,8", "iPad14,9"], 10.9, (59, 41), "iPad Air (11-inch) (M2)", "iPad Air (11-inch) (M2)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m2", True, True),
|
||
Device("iPadAir13M2", "Device is an [iPad Air 13-inch (M2)](https://support.apple.com/en-us/119893)", "https://cdsassets.apple.com/content/services/pub/image?productid=301029&size=240x240", ["iPad14,10", "iPad14,11"], 12.9, (683, 512), "iPad Air (13-inch) (M2)", "iPad Air (13-inch) (M2)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m2", True, True),
|
||
Device("iPadAir11M3", "Device is an [iPad Air 11-inch (M3)]()", "https://cdsassets.apple.com/content/services/pub/image?productid=301027&size=240x240", ["iPad15,3", "iPad15,4"], 10.9, (59, 41), "iPad Air (11-inch) (M3)", "iPad Air (11-inch) (M3)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m3", True, True),
|
||
Device("iPadAir13M3", "Device is an [iPad Air 13-inch (M3)]()", "https://cdsassets.apple.com/content/services/pub/image?productid=301029&size=240x240", ["iPad15,5", "iPad15,6"], 12.9, (683, 512), "iPad Air (13-inch) (M3)", "iPad Air (13-inch) (M3)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m3", True, True),
|
||
Device("iPadAir11M4", "Device is an [iPad Air 11-inch (M4)]()", "", ["iPad16,8", "iPad16,9"], 10.9, (59, 41), "iPad Air (11-inch) (M4)", "iPad Air (11-inch) (M4)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m4", True, True),
|
||
Device("iPadAir13M4", "Device is an [iPad Air 13-inch (M4)]()", "", ["iPad16,10", "iPad16,11"], 12.9, (683, 512), "iPad Air (13-inch) (M4)", "iPad Air (13-inch) (M4)", 264, False, False, False, False, True, False, False, False, True, False, 34, False, 1, False, "m4", True, True),
|
||
Device("iPadMini", "Device is an [iPad mini](https://support.apple.com/kb/SP661)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP661/sp661_ipad_mini_color.jpg", ["iPad2,5", "iPad2,6", "iPad2,7"], 7.9, (3, 4), "iPad mini", "iPad mini", 163, False, True, False, False, False, False, False, False, False, False, 0, False, 1, False, "a5", False, False),
|
||
Device("iPadMini2", "Device is an [iPad mini 2](https://support.apple.com/kb/SP693)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP693/SP693-specs_color-mul.png", ["iPad4,4", "iPad4,5", "iPad4,6"], 7.9, (3, 4), "iPad mini 2", "iPad mini 2", 326, False, True, False, False, False, False, False, False, False, False, 0, False, 1, False, "a7", False, False),
|
||
Device("iPadMini3", "Device is an [iPad mini 3](https://support.apple.com/kb/SP709)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP709/SP709-space_gray.jpeg", ["iPad4,7", "iPad4,8", "iPad4,9"], 7.9, (3, 4), "iPad mini 3", "iPad mini 3", 326, False, True, False, False, True, False, False, False, False, False, 0, False, 1, False, "a7", False, False),
|
||
Device("iPadMini4", "Device is an [iPad mini 4](https://support.apple.com/kb/SP725)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP725/SP725ipad-mini-4.png", ["iPad5,1", "iPad5,2"], 7.9, (3, 4), "iPad mini 4", "iPad mini 4", 326, False, True, False, False, True, False, False, False, False, False, 0, False, 1, False, "a8", False, False),
|
||
Device("iPadMini5", "Device is an [iPad mini (5th generation)](https://support.apple.com/kb/SP788)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP788/ipad-mini-2019.jpg", ["iPad11,1", "iPad11,2"], 7.9, (3, 4), "iPad mini (5th generation)", "iPad mini (5th generation)", 326, False, True, False, False, True, False, False, False, False, False, 1, False, 1, False, "a12Bionic", False, False),
|
||
Device("iPadMini6", "Device is an [iPad mini (6th generation)](https://support.apple.com/kb/SP850)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1097/en_US/ipad-mini-6gen-240.png", ["iPad14,1", "iPad14,2"], 8.3, (744, 1133), "iPad mini (6th generation)", "iPad mini (6th generation)", 326, False, True, False, False, True, False, False, False, True, False, 23, False, 1, False, "a15Bionic", True, True),
|
||
Device("iPadMiniA17Pro", "Device is an [iPad mini (A17 Pro)](https://support.apple.com/en-us/121456)", "https://cdsassets.apple.com/live/7WUAS350/images/tech-specs/iPad_mini_A17_Pro_Wi-Fi_Lineup_Print__USEN.png", ["iPad16,1", "iPad16,2"], 8.3, (744, 1133), "iPad mini (A17 Pro)", "iPad mini (A17 Pro)", 326, False, True, False, False, True, False, False, False, True, False, 34, False, 1, False, "a17Pro", True, True),
|
||
Device("iPadPro9Inch", "Device is an [iPad Pro 9.7-inch](https://support.apple.com/kb/SP739)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP739/SP739.png", ["iPad6,3", "iPad6,4"], 9.7, (3, 4), "iPad Pro (9.7-inch)", "iPad Pro (9.7-inch)", 264, False, False, True, False, True, False, False, False, False, False, 1, False, 1, False, "a9X", False, False),
|
||
Device("iPadPro12Inch", "Device is an [iPad Pro 12-inch](https://support.apple.com/kb/SP723)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP723/SP723-iPad_Pro_2x.png", ["iPad6,7", "iPad6,8"], 12.9, (3, 4), "iPad Pro (12.9-inch)", "iPad Pro (12.9-inch)", 264, False, False, True, False, True, False, False, False, False, False, 1, False, 1, False, "a9X", False, False),
|
||
Device("iPadPro12Inch2", "Device is an [iPad Pro 12-inch (2nd generation)](https://support.apple.com/kb/SP761)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP761/ipad-pro-12in-hero-201706.png", ["iPad7,1", "iPad7,2"], 12.9, (3, 4), "iPad Pro (12.9-inch) (2nd generation)", "iPad Pro (12.9-inch) (2nd generation)", 264, False, False, True, False, True, False, False, False, False, False, 1, False, 1, False, "a10XFusion", False, False),
|
||
Device("iPadPro10Inch", "Device is an [iPad Pro 10.5-inch](https://support.apple.com/kb/SP762)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP761/ipad-pro-10in-hero-201706.png", ["iPad7,3", "iPad7,4"], 10.5, (3, 4), "iPad Pro (10.5-inch)", "iPad Pro (10.5-inch)", 264, False, False, True, False, True, False, False, False, False, False, 1, False, 1, False, "a10XFusion", False, False),
|
||
Device("iPadPro11Inch", "Device is an [iPad Pro 11-inch](https://support.apple.com/kb/SP784)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP784/ipad-pro-11-2018_2x.png", ["iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4"], 11.0, (139, 199), "iPad Pro (11-inch)", "iPad Pro (11-inch)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 1, False, "a12XBionic", True, False),
|
||
Device("iPadPro12Inch3", "Device is an [iPad Pro 12.9-inch (3rd generation)](https://support.apple.com/kb/SP785)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP785/ipad-pro-12-2018_2x.png", ["iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8"], 12.9, (512, 683), "iPad Pro (12.9-inch) (3rd generation)", "iPad Pro (12.9-inch) (3rd generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 1, False, "a12XBionic", True, False),
|
||
Device("iPadPro11Inch2", "Device is an [iPad Pro 11-inch (2nd generation)](https://support.apple.com/kb/SP814)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP814/ipad-pro-11-2020.jpeg", ["iPad8,9", "iPad8,10"], 11.0, (139, 199), "iPad Pro (11-inch) (2nd generation)", "iPad Pro (11-inch) (2nd generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "a12ZBionic", True, False),
|
||
Device("iPadPro12Inch4", "Device is an [iPad Pro 12.9-inch (4th generation)](https://support.apple.com/kb/SP815)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP815/ipad-pro-12-2020.jpeg", ["iPad8,11", "iPad8,12"], 12.9, (512, 683), "iPad Pro (12.9-inch) (4th generation)", "iPad Pro (12.9-inch) (4th generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "a12ZBionic", True, False),
|
||
Device("iPadPro11Inch3", "Device is an [iPad Pro 11-inch (3rd generation)](https://support.apple.com/kb/SP843)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP843/ipad-pro-11_2x.png", ["iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7"], 11.0, (139, 199), "iPad Pro (11-inch) (3rd generation)", "iPad Pro (11-inch) (3rd generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "m1", True, True),
|
||
Device("iPadPro12Inch5", "Device is an [iPad Pro 12.9-inch (5th generation)](https://support.apple.com/kb/SP844)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP844/ipad-pro-12-9_2x.png", ["iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11"], 12.9, (512, 683), "iPad Pro (12.9-inch) (5th generation)", "iPad Pro (12.9-inch) (5th generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "m1", True, True),
|
||
Device("iPadPro11Inch4", "Device is an [iPad Pro 11-inch (4th generation)](https://support.apple.com/kb/SP882)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP882/ipad-pro-4gen-mainimage_2x.png", ["iPad14,3", "iPad14,4"], 11.0, (139, 199), "iPad Pro (11-inch) (4th generation)", "iPad Pro (11-inch) (4th generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "m2", True, True),
|
||
Device("iPadPro12Inch6", "Device is an [iPad Pro 12.9-inch (6th generation)](https://support.apple.com/kb/SP883)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP882/ipad-pro-4gen-mainimage_2x.png", ["iPad14,5", "iPad14,6"], 12.9, (512, 683), "iPad Pro (12.9-inch) (6th generation)", "iPad Pro (12.9-inch) (6th generation)", 264, False, False, True, False, False, True, False, False, True, False, 23, False, 13, True, "m2", True, True),
|
||
Device("iPadPro11M4", "Device is an [iPad Pro 11-inch (M4)](https://support.apple.com/en-us/119892)", "https://cdsassets.apple.com/content/services/pub/image?productid=301031&size=240x240", ["iPad16,3", "iPad16,4"], 11.0, (605, 417), "iPad Pro (11-inch) (M4)", "iPad Pro (11-inch) (M4)", 264, False, False, True, False, False, True, False, False, True, False, 34, False, 1, True, "m4", True, True),
|
||
Device("iPadPro13M4", "Device is an [iPad Pro 13-inch (M4)](https://support.apple.com/en-us/119891)", "https://cdsassets.apple.com/content/services/pub/image?productid=301033&size=240x240", ["iPad16,5", "iPad16,6"], 13.0, (4, 3), "iPad Pro (13-inch) (M4)", "iPad Pro (13-inch) (M4)", 264, False, False, True, False, False, True, False, False, True, False, 34, False, 1, True, "m4", True, True),
|
||
Device("iPadPro11M5", "Device is an [iPad Pro 11-inch (M5)](https://support.apple.com/en-us/125406)", "https://cdsassets.apple.com/content/services/pub/image?productid=301271&size=240x240", ["iPad17,1", "iPad17,2"], 11.0, (605, 417), "iPad Pro (11-inch) (M5)", "iPad Pro (11-inch) (M5)", 264, False, False, True, False, False, True, False, False, True, False, 234, False, 1, True, "m5", True, True),
|
||
Device("iPadPro13M5", "Device is an [iPad Pro 13-inch (M5)](https://support.apple.com/en-us/125406)", "https://cdsassets.apple.com/content/services/pub/image?productid=301273&size=240x240", ["iPad17,3", "iPad17,4"], 13.0, (4, 3), "iPad Pro (13-inch) (M5)", "iPad Pro (13-inch) (M5)", 264, False, False, True, False, False, True, False, False, True, False, 234, False, 1, True, "m5", True, True),
|
||
]
|
||
|
||
homePods = [
|
||
Device("homePod", "Device is a [HomePod](https://support.apple.com/kb/SP773)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP773/homepod_space_gray_large_2x.jpg", ["AudioAccessory1,1"], -1, (4, 5), "HomePod", "HomePod", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a8", False, False),
|
||
]
|
||
# tvOS
|
||
tvs = [
|
||
Device("appleTVHD", "Device is an [Apple TV HD](https://support.apple.com/kb/SP724) (Previously Apple TV (4th generation))", "http://images.apple.com/v/tv/c/images/overview/buy_tv_large_2x.jpg", ["AppleTV5,3"], 0, (), "Apple TV HD", "Apple TV HD", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a8", True, False),
|
||
Device("appleTV4K", "Device is an [Apple TV 4K](https://support.apple.com/kb/SP769)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP769/appletv4k.png", ["AppleTV6,2"], 0, (), "Apple TV 4K", "Apple TV 4K", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a10XFusion", False, False),
|
||
Device("appleTV4K2", "Device is an [Apple TV 4K (2nd generation)](https://support.apple.com/kb/SP845)", "https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/1000/IM1023/en_US/apple-tv-4k-2gen-240.png", ["AppleTV11,1"], 0, (), "Apple TV 4K (2nd generation)", "Apple TV 4K (2nd generation)", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a12Bionic", False, False),
|
||
Device("appleTV4K3", "Device is an [Apple TV 4K (3rd generation)](https://support.apple.com/kb/SP886)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP886/apple-tv-4k-3gen_2x.png", ["AppleTV14,1"], 0, (), "Apple TV 4K (3rd generation)", "Apple TV 4K (3rd generation)", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a15Bionic", False, False),
|
||
]
|
||
|
||
# watchOS
|
||
watches = [
|
||
Device(
|
||
"appleWatchSeries0_38mm",
|
||
"Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM784/en_US/apple_watch_sport-240.png",
|
||
["Watch1,1"], 1.5, (4,5), "Apple Watch (1st generation) 38mm", "Apple Watch (1st generation) 38mm", 290, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s1", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries0_42mm",
|
||
"Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM784/en_US/apple_watch_sport-240.png",
|
||
["Watch1,2"], 1.6, (4,5), "Apple Watch (1st generation) 42mm", "Apple Watch (1st generation) 42mm", 303, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s1", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries1_38mm",
|
||
"Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM848/en_US/applewatch-series2-aluminum-temp-240.png",
|
||
["Watch2,6"], 1.5, (4,5), "Apple Watch Series 1 38mm", "Apple Watch Series 1 38mm", 290, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s1P", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries1_42mm",
|
||
"Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM848/en_US/applewatch-series2-aluminum-temp-240.png",
|
||
["Watch2,7"], 1.6, (4,5), "Apple Watch Series 1 42mm", "Apple Watch Series 1 42mm", 303, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s1P", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries2_38mm",
|
||
"Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM852/en_US/applewatch-series2-hermes-240.png",
|
||
["Watch2,3"], 1.5, (4,5), "Apple Watch Series 2 38mm", "Apple Watch Series 2 38mm", 290, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s2", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries2_42mm",
|
||
"Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM852/en_US/applewatch-series2-hermes-240.png",
|
||
["Watch2,4"], 1.6, (4,5), "Apple Watch Series 2 42mm", "Apple Watch Series 2 42mm", 303, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s2", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries3_38mm",
|
||
"Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM893/en_US/apple-watch-s3-nikeplus-240.png",
|
||
["Watch3,1", "Watch3,3"], 1.5, (4,5), "Apple Watch Series 3 38mm", "Apple Watch Series 3 38mm", 290, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s3", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries3_42mm",
|
||
"Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM893/en_US/apple-watch-s3-nikeplus-240.png",
|
||
["Watch3,2", "Watch3,4"], 1.6, (4,5), "Apple Watch Series 3 42mm", "Apple Watch Series 3 42mm", 303, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s3", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries4_40mm",
|
||
"Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM911/en_US/aw-series4-nike-240.png",
|
||
["Watch4,1", "Watch4,3"], 1.8, (4,5), "Apple Watch Series 4 40mm", "Apple Watch Series 4 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s4", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries4_44mm",
|
||
"Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)",
|
||
"https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM911/en_US/aw-series4-nike-240.png",
|
||
["Watch4,2", "Watch4,4"], 2.0, (4,5), "Apple Watch Series 4 44mm", "Apple Watch Series 4 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s4", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries5_40mm",
|
||
"Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP808/sp808-apple-watch-series-5_2x.png",
|
||
["Watch5,1", "Watch5,3"], 1.8, (4,5), "Apple Watch Series 5 40mm", "Apple Watch Series 5 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s5", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries5_44mm",
|
||
"Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP808/sp808-apple-watch-series-5_2x.png",
|
||
["Watch5,2", "Watch5,4"], 2.0, (4,5), "Apple Watch Series 5 44mm", "Apple Watch Series 5 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, True, 0, False, "s5", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries6_40mm",
|
||
"Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP826/sp826-apple-watch-series6-580_2x.png",
|
||
["Watch6,1", "Watch6,3"], 1.8, (4,5), "Apple Watch Series 6 40mm", "Apple Watch Series 6 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s6", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries6_44mm",
|
||
"Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP826/sp826-apple-watch-series6-580_2x.png",
|
||
["Watch6,2", "Watch6,4"], 2.0, (4,5), "Apple Watch Series 6 44mm", "Apple Watch Series 6 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s6", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE_40mm",
|
||
"Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP827/sp827-apple-watch-se-580_2x.png",
|
||
["Watch5,9", "Watch5,11"], 1.8, (4,5), "Apple Watch SE 40mm", "Apple Watch SE 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s5", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE_44mm",
|
||
"Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP827/sp827-apple-watch-se-580_2x.png",
|
||
["Watch5,10", "Watch5,12"], 2.0, (4,5), "Apple Watch SE 44mm", "Apple Watch SE 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s5", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries7_41mm",
|
||
"Device is an [Apple Watch Series 7](https://support.apple.com/kb/SP860)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP860/series7-480_2x.png",
|
||
["Watch6,6", "Watch6,8"], 1.8, (4,5), "Apple Watch Series 7 41mm", "Apple Watch Series 7 41mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s7", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries7_45mm",
|
||
"Device is an [Apple Watch Series 7](https://support.apple.com/kb/SP860)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP860/series7-480_2x.png",
|
||
["Watch6,7", "Watch6,9"], 2.0, (4,5), "Apple Watch Series 7 45mm", "Apple Watch Series 7 45mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s7", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries8_41mm",
|
||
"Device is an [Apple Watch Series 8](https://support.apple.com/kb/SP878)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP878/apple-watch-series8_2x.png",
|
||
["Watch6,14", "Watch6,16"], 1.8, (4,5), "Apple Watch Series 8 41mm", "Apple Watch Series 8 41mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s8", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries8_45mm",
|
||
"Device is an [Apple Watch Series 8](https://support.apple.com/kb/SP878)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP878/apple-watch-series8_2x.png",
|
||
["Watch6,15", "Watch6,17"], 2.0, (4,5), "Apple Watch Series 8 45mm", "Apple Watch Series 8 45mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s8", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE2_40mm",
|
||
"Device is an [Apple Watch SE (2nd generation)](https://support.apple.com/kb/SP877)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP877/apple-watch-se-2nd-gen_2x.png",
|
||
["Watch6,10", "Watch6,12"], 1.8, (4,5), "Apple Watch SE (2nd generation) 40mm", "Apple Watch SE (2nd generation) 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s8", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE2_44mm",
|
||
"Device is an [Apple Watch SE (2nd generation)](https://support.apple.com/kb/SP877)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP877/apple-watch-se-2nd-gen_2x.png",
|
||
["Watch6,11", "Watch6,13"], 2.0, (4,5), "Apple Watch SE (2nd generation) 44mm", "Apple Watch SE (2nd generation) 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s8", False, False),
|
||
|
||
Device(
|
||
"appleWatchUltra",
|
||
"Device is an [Apple Watch Ultra](https://support.apple.com/kb/SP879)",
|
||
"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP879/apple-watch-ultra_2x.png",
|
||
["Watch6,18"], 2.2, (4,5), "Apple Watch Ultra", "Apple Watch Ultra", 338, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s8", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries9_41mm",
|
||
"Device is an [Apple Watch Series 9](https://support.apple.com/kb/SP905)",
|
||
"",
|
||
["Watch7,1", "Watch7,3"], 1.9, (4,5), "Apple Watch Series 9 41mm", "Apple Watch Series 9 41mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s9", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries9_45mm",
|
||
"Device is an [Apple Watch Series 9](https://support.apple.com/kb/SP905)",
|
||
"",
|
||
["Watch7,2", "Watch7,4"], 2.0, (4,5), "Apple Watch Series 9 45mm", "Apple Watch Series 9 45mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s9", False, False),
|
||
|
||
Device(
|
||
"appleWatchUltra2",
|
||
"Device is an [Apple Watch Ultra2]()",
|
||
"",
|
||
["Watch7,5"], 2.2, (4,5), "Apple Watch Ultra2", "Apple Watch Ultra2", 338, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s9", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE3_40mm",
|
||
"Device is an [Apple Watch SE (3rd generation)]()",
|
||
"",
|
||
["Watch7,13", "Watch7,14"], 1.8, (4,5), "Apple Watch SE (3rd generation) 40mm", "Apple Watch SE (3rd generation) 40mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchSE3_44mm",
|
||
"Device is an [Apple Watch SE (3rd generation)]()",
|
||
"",
|
||
["Watch7,15", "Watch7,16"], 2.0, (4,5), "Apple Watch SE (3rd generation) 44mm", "Apple Watch SE (3rd generation) 44mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries10_42mm",
|
||
"Device is an [Apple Watch Series 10]()",
|
||
"",
|
||
["Watch7,8", "Watch7,10"], 1.9, (374,446), "Apple Watch Series 10 42mm", "Apple Watch Series 10 42mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries10_46mm",
|
||
"Device is an [Apple Watch Series 10]()",
|
||
"",
|
||
["Watch7,9", "Watch7,11"], 2.0, (416,496), "Apple Watch Series 10 46mm", "Apple Watch Series 10 46mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchUltra3",
|
||
"Device is an [Apple Watch Ultra 3]()",
|
||
"",
|
||
["Watch7,12"], 2.2, (4,5), "Apple Watch Ultra 3", "Apple Watch Ultra 3", 338, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries11_42mm",
|
||
"Device is an [Apple Watch Series 11]()",
|
||
"",
|
||
["Watch7,17", "Watch7,19"], 1.9, (374,446), "Apple Watch Series 11 42mm", "Apple Watch Series 11 42mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
Device(
|
||
"appleWatchSeries11_46mm",
|
||
"Device is an [Apple Watch Series 11]()",
|
||
"",
|
||
["Watch7,18", "Watch7,20"], 2.0, (416,496), "Apple Watch Series 11 46mm", "Apple Watch Series 11 46mm", 326, False, False, False, False, False, False, False, True, False, False, 0, False, 0, False, "s10", False, False),
|
||
|
||
]
|
||
|
||
iOSDevices = iPods + iPhones + iPads + homePods
|
||
tvOSDevices = tvs
|
||
watchOSDevices = watches
|
||
}%
|
||
#if os(watchOS)
|
||
import WatchKit
|
||
#elseif canImport(UIKit)
|
||
import UIKit
|
||
#else
|
||
import Foundation
|
||
#endif
|
||
|
||
// MARK: Device
|
||
|
||
/// This enum is a value-type wrapper and extension of
|
||
/// [`UIDevice`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/).
|
||
///
|
||
/// Usage:
|
||
///
|
||
/// let device = Device.current
|
||
///
|
||
/// print(device) // prints, for example, "iPhone 6 Plus"
|
||
///
|
||
/// if device == .iPhone6Plus {
|
||
/// // Do something
|
||
/// } else {
|
||
/// // Do something else
|
||
/// }
|
||
///
|
||
/// ...
|
||
///
|
||
/// if device.batteryState == .full || device.batteryState >= .charging(75) {
|
||
/// print("Your battery is happy! 😊")
|
||
/// }
|
||
///
|
||
/// ...
|
||
///
|
||
/// if device.batteryLevel >= 50 {
|
||
/// install_iOS()
|
||
/// } else {
|
||
/// showError()
|
||
/// }
|
||
///
|
||
public enum Device {
|
||
#if os(iOS)
|
||
% for device in iOSDevices:
|
||
/// ${device.comment}
|
||
///
|
||
/// 
|
||
case ${device.caseName}
|
||
% end
|
||
#elseif os(tvOS)
|
||
% for device in tvOSDevices:
|
||
/// ${device.comment}
|
||
///
|
||
/// 
|
||
case ${device.caseName}
|
||
% end
|
||
#elseif os(watchOS)
|
||
% for device in watchOSDevices:
|
||
/// ${device.comment}
|
||
///
|
||
/// 
|
||
case ${device.caseName}
|
||
% end
|
||
#endif
|
||
|
||
/// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)
|
||
///
|
||
/// 
|
||
indirect case simulator(Device)
|
||
|
||
/// Device is not yet known (implemented)
|
||
/// You can still use this enum as before but the description equals the identifier (you can get multiple identifiers for the same product class
|
||
/// (e.g. "iPhone6,1" or "iPhone 6,2" do both mean "iPhone 5s"))
|
||
case unknown(String)
|
||
|
||
/// Returns a `Device` representing the current device this software runs on.
|
||
public static var current: Device {
|
||
return Device.mapToDevice(identifier: Device.identifier)
|
||
}
|
||
|
||
/// Gets the identifier from the system, such as "iPhone7,1".
|
||
public static var identifier: String = {
|
||
var systemInfo = utsname()
|
||
uname(&systemInfo)
|
||
let mirror = Mirror(reflecting: systemInfo.machine)
|
||
|
||
let identifier = mirror.children.reduce("") { identifier, element in
|
||
guard let value = element.value as? Int8, value != 0 else { return identifier }
|
||
return identifier + String(UnicodeScalar(UInt8(value)))
|
||
}
|
||
return identifier
|
||
}()
|
||
|
||
/// Maps an identifier to a Device. If the identifier can not be mapped to an existing device, `UnknownDevice(identifier)` is returned.
|
||
///
|
||
/// - parameter identifier: The device identifier, e.g. "iPhone7,1". Can be obtained from `Device.identifier`.
|
||
///
|
||
/// - returns: An initialized `Device`.
|
||
public static func mapToDevice(identifier: String) -> Device {
|
||
#if os(iOS)
|
||
switch identifier {
|
||
% for device in iOSDevices:
|
||
case ${', '.join(list(map(lambda device: "\"" + device + "\"", device.identifiers)))}: return ${device.caseName}
|
||
% end
|
||
case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))
|
||
default: return unknown(identifier)
|
||
}
|
||
#elseif os(tvOS)
|
||
switch identifier {
|
||
% for device in tvOSDevices:
|
||
case ${', '.join(list(map(lambda device: "\"" + device + "\"", device.identifiers)))}: return ${device.caseName}
|
||
% end
|
||
case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))
|
||
default: return unknown(identifier)
|
||
}
|
||
#elseif os(watchOS)
|
||
switch identifier {
|
||
% for device in watchOSDevices:
|
||
case ${', '.join(list(map(lambda device: "\"" + device + "\"", device.identifiers)))}: return ${device.caseName}
|
||
% end
|
||
case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "watchOS"))
|
||
default: return unknown(identifier)
|
||
}
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return unknown(identifier)
|
||
#else
|
||
return unknown(identifier)
|
||
#endif
|
||
}
|
||
|
||
/// Get the real device from a device.
|
||
/// If the device is a an iPhone8Plus simulator this function returns .iPhone8Plus (the real device).
|
||
/// If the parameter is a real device, this function returns just that passed parameter.
|
||
///
|
||
/// - parameter device: A device.
|
||
///
|
||
/// - returns: the underlying device If the `device` is a `simulator`,
|
||
/// otherwise return the `device`.
|
||
public static func realDevice(from device: Device) -> Device {
|
||
if case let .simulator(model) = device {
|
||
return model
|
||
}
|
||
return device
|
||
}
|
||
|
||
#if os(iOS) || os(watchOS)
|
||
/// Returns diagonal screen length in inches
|
||
public var diagonal: Double {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return ${device.diagonal}
|
||
% end
|
||
case .simulator(let model): return model.diagonal
|
||
case .unknown: return -1
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return ${device.diagonal}
|
||
% end
|
||
case .simulator(let model): return model.diagonal
|
||
case .unknown: return -1
|
||
}
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
/// Returns screen ratio as a tuple
|
||
public var screenRatio: (width: Double, height: Double) {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return (width: ${device.screenRatio[0]}, height: ${device.screenRatio[1]})
|
||
% end
|
||
case .simulator(let model): return model.screenRatio
|
||
case .unknown: return (width: -1, height: -1)
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return (width: ${device.screenRatio[0]}, height: ${device.screenRatio[1]})
|
||
% end
|
||
case .simulator(let model): return model.screenRatio
|
||
case .unknown: return (width: -1, height: -1)
|
||
}
|
||
#elseif os(tvOS) || os(visionOS)
|
||
return (width: -1, height: -1)
|
||
#else
|
||
return (width: -1, height: -1)
|
||
#endif
|
||
}
|
||
|
||
#if os(iOS)
|
||
/// All iPods
|
||
public static var allPods: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, iPods)))}]
|
||
}
|
||
|
||
/// All iPhones
|
||
public static var allPhones: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, iPhones)))}]
|
||
}
|
||
|
||
/// All iPads
|
||
public static var allPads: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, iPads)))}]
|
||
}
|
||
|
||
/// All X-Series Devices
|
||
@available(*, deprecated, renamed: "allDevicesWithSensorHousing")
|
||
public static var allXSeriesDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.isXSeries == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All Plus and Max-Sized Devices
|
||
public static var allPlusSizedDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.isPlusFormFactor == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All Pro Devices
|
||
public static var allProDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.isPro == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All mini Devices
|
||
public static var allMiniDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.isPadMiniFormFactor == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All simulator iPods
|
||
public static var allSimulatorPods: [Device] {
|
||
return allPods.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator iPhones
|
||
public static var allSimulatorPhones: [Device] {
|
||
return allPhones.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator iPads
|
||
public static var allSimulatorPads: [Device] {
|
||
return allPads.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator iPad mini
|
||
public static var allSimulatorMiniDevices: [Device] {
|
||
return allMiniDevices.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator X series Devices
|
||
@available(*, deprecated, renamed: "allSimulatorDevicesWithSensorHousing")
|
||
public static var allSimulatorXSeriesDevices: [Device] {
|
||
return allDevicesWithSensorHousing.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator Plus and Max-Sized Devices
|
||
public static var allSimulatorPlusSizedDevices: [Device] {
|
||
return allPlusSizedDevices.map(Device.simulator)
|
||
}
|
||
|
||
/// All simulator Pro Devices
|
||
public static var allSimulatorProDevices: [Device] {
|
||
return allProDevices.map(Device.simulator)
|
||
}
|
||
|
||
/// Returns whether the device is an iPod (real or simulator)
|
||
public var isPod: Bool {
|
||
return isOneOf(Device.allPods) || isOneOf(Device.allSimulatorPods)
|
||
}
|
||
|
||
/// Returns whether the device is an iPhone (real or simulator)
|
||
public var isPhone: Bool {
|
||
return (isOneOf(Device.allPhones)
|
||
|| isOneOf(Device.allSimulatorPhones)
|
||
|| (UIDevice.current.userInterfaceIdiom == .phone && isCurrent)) && !isPod
|
||
}
|
||
|
||
/// Returns whether the device is an iPad (real or simulator)
|
||
public var isPad: Bool {
|
||
return isOneOf(Device.allPads)
|
||
|| isOneOf(Device.allSimulatorPads)
|
||
|| (UIDevice.current.userInterfaceIdiom == .pad && isCurrent)
|
||
}
|
||
|
||
/// If this device is a simulator return the underlying device,
|
||
/// otherwise return `self`.
|
||
public var realDevice: Device {
|
||
return Device.realDevice(from: self)
|
||
}
|
||
|
||
public var isZoomed: Bool? {
|
||
guard isCurrent else { return nil }
|
||
if Int(UIScreen.main.scale.rounded()) == 3 {
|
||
// Plus-sized
|
||
return UIScreen.main.nativeScale > 2.7 && UIScreen.main.nativeScale < 3
|
||
} else {
|
||
return UIScreen.main.nativeScale > UIScreen.main.scale
|
||
}
|
||
}
|
||
|
||
/// All Touch ID Capable Devices
|
||
public static var allTouchIDCapableDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasTouchID == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All Face ID Capable Devices
|
||
public static var allFaceIDCapableDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasFaceID == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All Devices with Touch ID or Face ID
|
||
public static var allBiometricAuthenticationCapableDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasTouchID == True or device.hasFaceID == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has Touch ID
|
||
public var isTouchIDCapable: Bool {
|
||
return isOneOf(Device.allTouchIDCapableDevices) || isOneOf(Device.allTouchIDCapableDevices.map(Device.simulator))
|
||
}
|
||
|
||
/// Returns whether or not the device has Face ID
|
||
public var isFaceIDCapable: Bool {
|
||
return isOneOf(Device.allFaceIDCapableDevices) || isOneOf(Device.allFaceIDCapableDevices.map(Device.simulator))
|
||
}
|
||
|
||
/// Returns whether or not the device has any biometric sensor (i.e. Touch ID or Face ID)
|
||
public var hasBiometricSensor: Bool {
|
||
return isTouchIDCapable || isFaceIDCapable
|
||
}
|
||
|
||
/// All devices that feature a sensor housing in the screen
|
||
public static var allDevicesWithSensorHousing: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasSensorHousing == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All simulator devices that feature a sensor housing in the screen
|
||
public static var allSimulatorDevicesWithSensorHousing: [Device] {
|
||
return allDevicesWithSensorHousing.map(Device.simulator)
|
||
}
|
||
|
||
/// Returns whether or not the device has a sensor housing
|
||
public var hasSensorHousing: Bool {
|
||
return isOneOf(Device.allDevicesWithSensorHousing) || isOneOf(Device.allDevicesWithSensorHousing.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that feature a screen with rounded corners.
|
||
public static var allDevicesWithRoundedDisplayCorners: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasRoundedDisplayCorners == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has a screen with rounded corners.
|
||
public var hasRoundedDisplayCorners: Bool {
|
||
return isOneOf(Device.allDevicesWithRoundedDisplayCorners) || isOneOf(Device.allDevicesWithRoundedDisplayCorners.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that have the Dynamic Island.
|
||
public static var allDevicesWithDynamicIsland: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasDynamicIsland == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has the Dynamic Island.
|
||
public var hasDynamicIsland: Bool {
|
||
return isOneOf(Device.allDevicesWithDynamicIsland) || isOneOf(Device.allDevicesWithDynamicIsland.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that have 3D Touch support.
|
||
public static var allDevicesWith3dTouchSupport: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasForce3dTouchSupport == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has 3D Touch support.
|
||
public var has3dTouchSupport: Bool {
|
||
return isOneOf(Device.allDevicesWith3dTouchSupport) || isOneOf(Device.allDevicesWith3dTouchSupport.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that support wireless charging.
|
||
public static var allDevicesWithWirelessChargingSupport: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.supportsWirelessCharging == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device supports wireless charging.
|
||
public var supportsWirelessCharging: Bool {
|
||
return isOneOf(Device.allDevicesWithWirelessChargingSupport) || isOneOf(Device.allDevicesWithWirelessChargingSupport.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that support 5G.
|
||
public static var allDevicesWith5gSupport: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.has5gSupport == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has 5G support.
|
||
public var has5gSupport: Bool {
|
||
return isOneOf(Device.allDevicesWith5gSupport) || isOneOf(Device.allDevicesWith5gSupport.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that have a LiDAR sensor.
|
||
public static var allDevicesWithALidarSensor: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasLidarSensor == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has a LiDAR sensor.
|
||
public var hasLidarSensor: Bool {
|
||
return isOneOf(Device.allDevicesWithALidarSensor) || isOneOf(Device.allDevicesWithALidarSensor.map(Device.simulator))
|
||
}
|
||
|
||
/// All devices that have a USB-C connectivity.
|
||
public static var allDevicesWithUSBCConnectivity: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasUSBCConnectivity == True, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has a USB-C power supply.
|
||
public var hasUSBCConnectivity: Bool {
|
||
return isOneOf(Device.allDevicesWithUSBCConnectivity) || isOneOf(Device.allDevicesWithUSBCConnectivity.map(Device.simulator))
|
||
}
|
||
#elseif os(tvOS)
|
||
/// All TVs
|
||
public static var allTVs: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, tvOSDevices)))}]
|
||
}
|
||
|
||
/// All simulator TVs
|
||
public static var allSimulatorTVs: [Device] {
|
||
return allTVs.map(Device.simulator)
|
||
}
|
||
#elseif os(watchOS)
|
||
/// All Watches
|
||
public static var allWatches: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, watchOSDevices)))}]
|
||
}
|
||
|
||
/// All simulator Watches
|
||
public static var allSimulatorWatches: [Device] {
|
||
return allWatches.map(Device.simulator)
|
||
}
|
||
|
||
/// All watches that have Force Touch support.
|
||
public static var allWatchesWithForceTouchSupport: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasForce3dTouchSupport == True, watchOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the device has Force Touch support.
|
||
public var hasForceTouchSupport: Bool {
|
||
return isOneOf(Device.allWatchesWithForceTouchSupport) || isOneOf(Device.allWatchesWithForceTouchSupport.map(Device.simulator))
|
||
}
|
||
#endif
|
||
|
||
/// Returns whether the current device is a SwiftUI preview canvas
|
||
public var isCanvas: Bool? {
|
||
guard isCurrent else { return nil }
|
||
#if DEBUG
|
||
return ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
|
||
#else
|
||
return false
|
||
#endif
|
||
}
|
||
|
||
/// All real devices (i.e. all devices except for all simulators)
|
||
public static var allRealDevices: [Device] {
|
||
#if os(iOS)
|
||
return allPods + allPhones + allPads
|
||
#elseif os(tvOS)
|
||
return allTVs
|
||
#elseif os(watchOS)
|
||
return allWatches
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return []
|
||
#else
|
||
return []
|
||
#endif
|
||
}
|
||
|
||
/// All simulators
|
||
public static var allSimulators: [Device] {
|
||
return allRealDevices.map(Device.simulator)
|
||
}
|
||
|
||
/// Returns whether the device is any of the simulator
|
||
/// Useful when there is a need to check and skip running a portion of code (location request or others)
|
||
public var isSimulator: Bool {
|
||
return isOneOf(Device.allSimulators)
|
||
}
|
||
|
||
/**
|
||
This method saves you in many cases from the need of updating your code with every new device.
|
||
Most uses for an enum like this are the following:
|
||
|
||
```
|
||
switch Device.current {
|
||
case .iPodTouch5, .iPodTouch6: callMethodOnIPods()
|
||
case .iPhone4, iPhone4s, .iPhone5, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX: callMethodOnIPhones()
|
||
case .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadPro: callMethodOnIPads()
|
||
default: break
|
||
}
|
||
```
|
||
This code can now be replaced with
|
||
|
||
```
|
||
let device = Device.current
|
||
if device.isOneOf(Device.allPods) {
|
||
callMethodOnIPods()
|
||
} else if device.isOneOf(Device.allPhones) {
|
||
callMethodOnIPhones()
|
||
} else if device.isOneOf(Device.allPads) {
|
||
callMethodOnIPads()
|
||
}
|
||
```
|
||
|
||
- parameter devices: An array of devices.
|
||
|
||
- returns: Returns whether the current device is one of the passed in ones.
|
||
*/
|
||
public func isOneOf(_ devices: [Device]) -> Bool {
|
||
return devices.contains(self)
|
||
}
|
||
|
||
// MARK: Current Device
|
||
|
||
/// Whether or not the current device is the current device.
|
||
private var isCurrent: Bool {
|
||
return self == Device.current
|
||
}
|
||
|
||
/// The name identifying the device (e.g. "Dennis' iPhone").
|
||
/// As of iOS 16, this will return a generic String like "iPhone", unless your app has additional entitlements.
|
||
/// See the follwing link for more information: https://developer.apple.com/documentation/uikit/uidevice/1620015-name
|
||
public var name: String? {
|
||
guard isCurrent else { return nil }
|
||
#if os(watchOS)
|
||
return WKInterfaceDevice.current().name
|
||
#elseif canImport(UIKit)
|
||
return UIDevice.current.name
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// The name of the operating system running on the device represented by the receiver (e.g. "iOS" or "tvOS").
|
||
public var systemName: String? {
|
||
guard isCurrent else { return nil }
|
||
#if os(watchOS)
|
||
return WKInterfaceDevice.current().systemName
|
||
#elseif os(iOS)
|
||
if isPad, #available(iOS 13, *), UIDevice.current.systemName == "iOS" {
|
||
return "iPadOS"
|
||
} else {
|
||
return UIDevice.current.systemName
|
||
}
|
||
#elseif canImport(UIKit)
|
||
return UIDevice.current.systemName
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// The current version of the operating system (e.g. 8.4 or 9.2).
|
||
public var systemVersion: String? {
|
||
guard isCurrent else { return nil }
|
||
#if os(watchOS)
|
||
return WKInterfaceDevice.current().systemVersion
|
||
#elseif canImport(UIKit)
|
||
return UIDevice.current.systemVersion
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// The model of the device (e.g. "iPhone" or "iPod Touch").
|
||
public var model: String? {
|
||
guard isCurrent else { return nil }
|
||
#if os(watchOS)
|
||
return WKInterfaceDevice.current().model
|
||
#elseif canImport(UIKit)
|
||
return UIDevice.current.model
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// The model of the device as a localized string.
|
||
public var localizedModel: String? {
|
||
guard isCurrent else { return nil }
|
||
#if os(watchOS)
|
||
return WKInterfaceDevice.current().localizedModel
|
||
#elseif canImport(UIKit)
|
||
return UIDevice.current.localizedModel
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// PPI (Pixels per Inch) on the current device's screen (if applicable). When the device is not applicable this property returns nil.
|
||
public var ppi: Int? {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return ${device.ppi}
|
||
% end
|
||
case .simulator(let model): return model.ppi
|
||
case .unknown: return nil
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return ${device.ppi}
|
||
% end
|
||
case .simulator(let model): return model.ppi
|
||
case .unknown: return nil
|
||
}
|
||
#elseif os(tvOS)
|
||
return nil
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return nil
|
||
#else
|
||
return nil
|
||
#endif
|
||
}
|
||
|
||
/// True when a Guided Access session is currently active; otherwise, false.
|
||
public var isGuidedAccessSessionActive: Bool {
|
||
#if os(iOS)
|
||
#if swift(>=4.2)
|
||
return UIAccessibility.isGuidedAccessEnabled
|
||
#else
|
||
return UIAccessibilityIsGuidedAccessEnabled()
|
||
#endif
|
||
#else
|
||
return false
|
||
#endif
|
||
}
|
||
|
||
/// The brightness level of the screen.
|
||
public var screenBrightness: Int {
|
||
#if os(iOS)
|
||
return Int(UIScreen.main.brightness * 100)
|
||
#else
|
||
return 100
|
||
#endif
|
||
}
|
||
}
|
||
|
||
// MARK: CustomStringConvertible
|
||
extension Device: CustomStringConvertible {
|
||
|
||
/// A textual representation of the device.
|
||
public var description: String {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return "${device.description}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.description))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return "${device.description}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.description))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(tvOS)
|
||
switch self {
|
||
% for device in tvOSDevices:
|
||
case .${device.caseName}: return "${device.description}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.description))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return "Apple Vision Pro"
|
||
#else
|
||
switch self {
|
||
case .simulator(let model): return "Simulator (\(model.description))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/// A safe version of `description`.
|
||
/// Example:
|
||
/// Device.iPhoneXR.description: iPhone Xʀ
|
||
/// Device.iPhoneXR.safeDescription: iPhone XR
|
||
public var safeDescription: String {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return "${device.safeDescription}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.safeDescription))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return "${device.safeDescription}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.safeDescription))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(tvOS)
|
||
switch self {
|
||
% for device in tvOSDevices:
|
||
case .${device.caseName}: return "${device.safeDescription}"
|
||
% end
|
||
case .simulator(let model): return "Simulator (\(model.safeDescription))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return "Apple Vision Pro"
|
||
#else
|
||
switch self {
|
||
case .simulator(let model): return "Simulator (\(model.safeDescription))"
|
||
case .unknown(let identifier): return identifier
|
||
}
|
||
#endif
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: Equatable
|
||
extension Device: Equatable {
|
||
|
||
/// Compares two devices
|
||
///
|
||
/// - parameter lhs: A device.
|
||
/// - parameter rhs: Another device.
|
||
///
|
||
/// - returns: `true` iff the underlying identifier is the same.
|
||
public static func == (lhs: Device, rhs: Device) -> Bool {
|
||
return lhs.description == rhs.description
|
||
}
|
||
|
||
}
|
||
|
||
// MARK: Battery
|
||
#if os(iOS) || os(watchOS)
|
||
@available(iOS 8.0, watchOS 4.0, *)
|
||
extension Device {
|
||
/**
|
||
This enum describes the state of the battery.
|
||
|
||
- Full: The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
|
||
- Charging: The device is plugged into power and the battery is less than 100% charged.
|
||
- Unplugged: The device is not plugged into power; the battery is discharging.
|
||
*/
|
||
public enum BatteryState: CustomStringConvertible, Equatable {
|
||
/// The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
|
||
case full
|
||
/// The device is plugged into power and the battery is less than 100% charged.
|
||
/// The associated value is in percent (0-100).
|
||
case charging(Int)
|
||
/// The device is not plugged into power; the battery is discharging.
|
||
/// The associated value is in percent (0-100).
|
||
case unplugged(Int)
|
||
|
||
#if os(iOS)
|
||
fileprivate init() {
|
||
let wasBatteryMonitoringEnabled = UIDevice.current.isBatteryMonitoringEnabled
|
||
UIDevice.current.isBatteryMonitoringEnabled = true
|
||
let batteryLevel = Int(round(UIDevice.current.batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number
|
||
// but maybe that changes in the future.
|
||
switch UIDevice.current.batteryState {
|
||
case .charging: self = .charging(batteryLevel)
|
||
case .full: self = .full
|
||
case .unplugged: self = .unplugged(batteryLevel)
|
||
case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
|
||
@unknown default:
|
||
self = .full // To cover any future additions for which DeviceKit might not have updated yet.
|
||
}
|
||
UIDevice.current.isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
|
||
}
|
||
#elseif os(watchOS)
|
||
fileprivate init() {
|
||
let wasBatteryMonitoringEnabled = WKInterfaceDevice.current().isBatteryMonitoringEnabled
|
||
WKInterfaceDevice.current().isBatteryMonitoringEnabled = true
|
||
let batteryLevel = Int(round(WKInterfaceDevice.current().batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number
|
||
// but maybe that changes in the future.
|
||
switch WKInterfaceDevice.current().batteryState {
|
||
case .charging: self = .charging(batteryLevel)
|
||
case .full: self = .full
|
||
case .unplugged: self = .unplugged(batteryLevel)
|
||
case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
|
||
@unknown default:
|
||
self = .full // To cover any future additions for which DeviceKit might not have updated yet.
|
||
}
|
||
WKInterfaceDevice.current().isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
|
||
}
|
||
#endif
|
||
|
||
/// The user enabled Low Power mode
|
||
public var lowPowerMode: Bool {
|
||
return ProcessInfo.processInfo.isLowPowerModeEnabled
|
||
}
|
||
|
||
/// Provides a textual representation of the battery state.
|
||
/// Examples:
|
||
/// ```
|
||
/// Battery level: 90%, device is plugged in.
|
||
/// Battery level: 100 % (Full), device is plugged in.
|
||
/// Battery level: \(batteryLevel)%, device is unplugged.
|
||
/// ```
|
||
public var description: String {
|
||
switch self {
|
||
case .charging(let batteryLevel): return "Battery level: \(batteryLevel)%, device is plugged in."
|
||
case .full: return "Battery level: 100 % (Full), device is plugged in."
|
||
case .unplugged(let batteryLevel): return "Battery level: \(batteryLevel)%, device is unplugged."
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/// The state of the battery
|
||
public var batteryState: BatteryState? {
|
||
guard isCurrent else { return nil }
|
||
return BatteryState()
|
||
}
|
||
|
||
/// Battery level ranges from 0 (fully discharged) to 100 (100% charged).
|
||
public var batteryLevel: Int? {
|
||
guard isCurrent else { return nil }
|
||
switch BatteryState() {
|
||
case .charging(let value): return value
|
||
case .full: return 100
|
||
case .unplugged(let value): return value
|
||
}
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
// MARK: Device.Batterystate: Comparable
|
||
#if os(iOS) || os(watchOS)
|
||
@available(iOS 8.0, watchOS 4.0, *)
|
||
extension Device.BatteryState: Comparable {
|
||
/// Tells if two battery states are equal.
|
||
///
|
||
/// - parameter lhs: A battery state.
|
||
/// - parameter rhs: Another battery state.
|
||
///
|
||
/// - returns: `true` iff they are equal, otherwise `false`
|
||
public static func == (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
|
||
return lhs.description == rhs.description
|
||
}
|
||
|
||
/// Compares two battery states.
|
||
///
|
||
/// - parameter lhs: A battery state.
|
||
/// - parameter rhs: Another battery state.
|
||
///
|
||
/// - returns: `true` if rhs is `.Full`, `false` when lhs is `.Full` otherwise their battery level is compared.
|
||
public static func < (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
|
||
switch (lhs, rhs) {
|
||
case (.full, _): return false // return false (even if both are `.Full` -> they are equal)
|
||
case (_, .full): return true // lhs is *not* `.Full`, rhs is
|
||
case let (.charging(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
|
||
case let (.charging(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
|
||
case let (.unplugged(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
|
||
case let (.unplugged(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
|
||
default: return false // compiler won't compile without it, though it cannot happen
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if os(iOS)
|
||
extension Device {
|
||
// MARK: Orientation
|
||
/**
|
||
This enum describes the state of the orientation.
|
||
- Landscape: The device is in Landscape Orientation
|
||
- Portrait: The device is in Portrait Orientation
|
||
- Unknown: The device orientation is unknown.
|
||
*/
|
||
public enum Orientation {
|
||
case landscape
|
||
case portrait
|
||
case unknown
|
||
}
|
||
|
||
public var orientation: Orientation {
|
||
if UIDevice.current.orientation.isLandscape {
|
||
return .landscape
|
||
} else if UIDevice.current.orientation.isPortrait {
|
||
return .portrait
|
||
} else {
|
||
return .unknown
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if os(iOS)
|
||
// MARK: DiskSpace
|
||
extension Device {
|
||
|
||
/// Return the root url
|
||
///
|
||
/// - returns: the NSHomeDirectory() url
|
||
private static let rootURL = URL(fileURLWithPath: NSHomeDirectory())
|
||
|
||
/// The volume’s total capacity in bytes.
|
||
public static var volumeTotalCapacity: Int? {
|
||
return (try? Device.rootURL.resourceValues(forKeys: [.volumeTotalCapacityKey]))?.volumeTotalCapacity
|
||
}
|
||
|
||
/// The volume’s available capacity in bytes.
|
||
public static var volumeAvailableCapacity: Int? {
|
||
return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityKey]))?.volumeAvailableCapacity
|
||
}
|
||
|
||
/// The volume’s available capacity in bytes for storing important resources.
|
||
@available(iOS 11.0, *)
|
||
public static var volumeAvailableCapacityForImportantUsage: Int64? {
|
||
return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]))?.volumeAvailableCapacityForImportantUsage
|
||
}
|
||
|
||
/// The volume’s available capacity in bytes for storing nonessential resources.
|
||
@available(iOS 11.0, *)
|
||
public static var volumeAvailableCapacityForOpportunisticUsage: Int64? { // swiftlint:disable:this identifier_name
|
||
return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForOpportunisticUsageKey]))?.volumeAvailableCapacityForOpportunisticUsage
|
||
}
|
||
|
||
/// All volumes capacity information in bytes.
|
||
@available(iOS 11.0, *)
|
||
public static var volumes: [URLResourceKey: Int64]? {
|
||
do {
|
||
let values = try rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey,
|
||
.volumeAvailableCapacityKey,
|
||
.volumeAvailableCapacityForOpportunisticUsageKey,
|
||
.volumeTotalCapacityKey
|
||
])
|
||
return values.allValues.mapValues {
|
||
if let int = $0 as? Int64 {
|
||
return int
|
||
}
|
||
if let int = $0 as? Int {
|
||
return Int64(int)
|
||
}
|
||
return 0
|
||
}
|
||
} catch {
|
||
return nil
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if os(iOS)
|
||
// MARK: Apple Pencil
|
||
extension Device {
|
||
|
||
/**
|
||
This option set describes the current Apple Pencils
|
||
- firstGeneration: 1st Generation Apple Pencil
|
||
- secondGeneration: 2nd Generation Apple Pencil
|
||
- firstGenerationUsbC: 1st Generation Apple Pencil (USB-C)
|
||
- pro: Apple Pencil Pro
|
||
*/
|
||
public struct ApplePencilSupport: OptionSet {
|
||
|
||
public var rawValue: UInt
|
||
|
||
public init(rawValue: UInt) {
|
||
self.rawValue = rawValue
|
||
}
|
||
|
||
public static let firstGeneration = ApplePencilSupport(rawValue: 0x01)
|
||
public static let secondGeneration = ApplePencilSupport(rawValue: 0x02)
|
||
public static let firstGenerationUsbC = ApplePencilSupport(rawValue: 0x04)
|
||
public static let pro = ApplePencilSupport(rawValue: 0x08)
|
||
}
|
||
|
||
/// All Apple Pencil Capable Devices
|
||
public static var allApplePencilCapableDevices: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.applePencilSupport != 0, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns supported version of the Apple Pencil
|
||
public var applePencilSupport: ApplePencilSupport {
|
||
switch self {
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 1, iOSDevices)):
|
||
case .${device.caseName}: return .firstGeneration
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 2, iOSDevices)):
|
||
case .${device.caseName}: return .secondGeneration
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 3, iOSDevices)):
|
||
case .${device.caseName}: return .firstGenerationUsbC
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 4, iOSDevices)):
|
||
case .${device.caseName}: return [.pro]
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 13, iOSDevices)):
|
||
case .${device.caseName}: return [.firstGeneration, .firstGenerationUsbC]
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 23, iOSDevices)):
|
||
case .${device.caseName}: return [.secondGeneration, .firstGenerationUsbC]
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 234, iOSDevices)):
|
||
case .${device.caseName}: return [.secondGeneration, .firstGenerationUsbC, .pro]
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 24, iOSDevices)):
|
||
case .${device.caseName}: return [.secondGeneration, .pro]
|
||
% end
|
||
% for device in list(filter(lambda device: device.applePencilSupport == 34, iOSDevices)):
|
||
case .${device.caseName}: return [.firstGenerationUsbC, .pro]
|
||
% end
|
||
case .simulator(let model): return model.applePencilSupport
|
||
default: return []
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if os(iOS)
|
||
// MARK: Cameras
|
||
extension Device {
|
||
|
||
public enum CameraType {
|
||
@available(*, deprecated, renamed: "wide")
|
||
case normal
|
||
|
||
case wide
|
||
case telephoto
|
||
case ultraWide
|
||
}
|
||
|
||
/// Returns an array of the types of cameras the device has
|
||
public var cameras: [CameraType] {
|
||
switch self {
|
||
% for device in list(filter(lambda device: device.cameras == 1, iOSDevices)):
|
||
case .${device.caseName}: return [.wide]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 2, iOSDevices)):
|
||
case .${device.caseName}: return [.telephoto]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 3, iOSDevices)):
|
||
case .${device.caseName}: return [.ultraWide]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 12, iOSDevices)):
|
||
case .${device.caseName}: return [.wide, .telephoto]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 13, iOSDevices)):
|
||
case .${device.caseName}: return [.wide, .ultraWide]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 23, iOSDevices)):
|
||
case .${device.caseName}: return [.telephoto, .ultraWide]
|
||
% end
|
||
% for device in list(filter(lambda device: device.cameras == 123, iOSDevices)):
|
||
case .${device.caseName}: return [.wide, .telephoto, .ultraWide]
|
||
% end
|
||
default: return []
|
||
}
|
||
}
|
||
|
||
/// All devices that feature a camera
|
||
public static var allDevicesWithCamera: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.cameras != 0, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All devices that feature a normal camera
|
||
@available(*, deprecated, renamed: "allDevicesWithWideCamera")
|
||
public static var allDevicesWithNormalCamera: [Device] {
|
||
return Device.allDevicesWithWideCamera
|
||
}
|
||
|
||
/// All devices that feature a wide camera
|
||
public static var allDevicesWithWideCamera: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.cameras == 1 or device.cameras == 12 or device.cameras == 13 or device.cameras == 123, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All devices that feature a telephoto camera
|
||
public static var allDevicesWithTelephotoCamera: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.cameras == 2 or device.cameras == 12 or device.cameras == 123, iOSDevices)))))}]
|
||
}
|
||
|
||
/// All devices that feature an ultra wide camera
|
||
public static var allDevicesWithUltraWideCamera: [Device] {
|
||
return [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.cameras == 3 or device.cameras == 13 or device.cameras == 123, iOSDevices)))))}]
|
||
}
|
||
|
||
/// Returns whether or not the current device has a camera
|
||
public var hasCamera: Bool {
|
||
return !self.cameras.isEmpty
|
||
}
|
||
|
||
/// Returns whether or not the current device has a normal camera
|
||
@available(*, deprecated, renamed: "hasWideCamera")
|
||
public var hasNormalCamera: Bool {
|
||
return self.hasWideCamera
|
||
}
|
||
|
||
/// Returns whether or not the current device has a wide camera
|
||
public var hasWideCamera: Bool {
|
||
return self.cameras.contains(.wide)
|
||
}
|
||
|
||
/// Returns whether or not the current device has a telephoto camera
|
||
public var hasTelephotoCamera: Bool {
|
||
return self.cameras.contains(.telephoto)
|
||
}
|
||
|
||
/// Returns whether or not the current device has an ultra wide camera
|
||
public var hasUltraWideCamera: Bool {
|
||
return self.cameras.contains(.ultraWide)
|
||
}
|
||
}
|
||
#endif
|
||
|
||
// MARK: ThermalState
|
||
@available(iOS 11.0, watchOS 4.0, macOS 10.10.3, tvOS 11.0, *)
|
||
extension Device {
|
||
/// The thermal state of the system.
|
||
public enum ThermalState {
|
||
/// The thermal state is within normal limits.
|
||
case nominal
|
||
/// The thermal state is slightly elevated.
|
||
case fair
|
||
/// The thermal state is high.
|
||
case serious
|
||
/// The thermal state is significantly impacting the performance of the system and the device needs to cool down.
|
||
case critical
|
||
}
|
||
|
||
/// Returns the current thermal state of the system (or nil if not called against the `current` device)
|
||
public var thermalState: ThermalState? {
|
||
guard isCurrent else { return nil }
|
||
switch ProcessInfo().thermalState {
|
||
case .nominal:
|
||
return .nominal
|
||
case .fair:
|
||
return .fair
|
||
case .serious:
|
||
return .serious
|
||
case .critical:
|
||
return .critical
|
||
@unknown default:
|
||
return .nominal
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: CPU
|
||
%{
|
||
class CPU:
|
||
def __init__(self, name, description):
|
||
self.name = name
|
||
self.description = description
|
||
|
||
# iOS
|
||
iOS_cpus = [
|
||
CPU("a4", "A4"),
|
||
CPU("a5", "A5"),
|
||
CPU("a5X", "A5X"),
|
||
CPU("a6", "A6"),
|
||
CPU("a6X", "A6X"),
|
||
CPU("a7", "A7"),
|
||
CPU("a8", "A8"),
|
||
CPU("a8X", "A8X"),
|
||
CPU("a9", "A9"),
|
||
CPU("a9X", "A9X"),
|
||
CPU("a10Fusion", "A10 Fusion"),
|
||
CPU("a10XFusion", "A10X Fusion"),
|
||
CPU("a11Bionic", "A11 Bionic"),
|
||
CPU("a12Bionic", "A12 Bionic"),
|
||
CPU("a12XBionic", "A12X Bionic"),
|
||
CPU("a12ZBionic", "A12Z Bionic"),
|
||
CPU("a13Bionic", "A13 Bionic"),
|
||
CPU("a14Bionic", "A14 Bionic"),
|
||
CPU("a15Bionic", "A15 Bionic"),
|
||
CPU("a16Bionic", "A16 Bionic"),
|
||
CPU("a17Pro" , "A17 Pro"),
|
||
CPU("a18" , "A18"),
|
||
CPU("a18Pro" , "A18 Pro"),
|
||
CPU("a19" , "A19"),
|
||
CPU("a19Pro" , "A19 Pro"),
|
||
CPU("m1", "M1"),
|
||
CPU("m2", "M2"),
|
||
CPU("m3", "M3"),
|
||
CPU("m4", "M4"),
|
||
CPU("m5", "M5"),
|
||
]
|
||
|
||
watchOS_cpus = [
|
||
CPU("s1", "S1"),
|
||
CPU("s1P", "S1P"),
|
||
CPU("s2", "S2"),
|
||
CPU("s3", "S3"),
|
||
CPU("s4", "S4"),
|
||
CPU("s5", "S5"),
|
||
CPU("s6", "S6"),
|
||
CPU("s7", "S7"),
|
||
CPU("s8", "S8"),
|
||
CPU("s9", "S9"),
|
||
CPU("s10", "S10"),
|
||
]
|
||
}%
|
||
|
||
extension Device {
|
||
|
||
public enum CPU: Comparable {
|
||
#if os(iOS) || os(tvOS)
|
||
% for cpu in iOS_cpus:
|
||
case ${cpu.name}
|
||
% end
|
||
#elseif os(watchOS)
|
||
% for cpu in watchOS_cpus:
|
||
case ${cpu.name}
|
||
% end
|
||
#endif
|
||
case unknown
|
||
}
|
||
|
||
/// Returns the cpu (SoC) that the device uses
|
||
public var cpu: CPU {
|
||
#if os(iOS)
|
||
switch self {
|
||
% for device in iOSDevices:
|
||
case .${device.caseName}: return .${device.cpu}
|
||
% end
|
||
case .simulator(let model): return model.cpu
|
||
case .unknown: return .unknown
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for device in watchOSDevices:
|
||
case .${device.caseName}: return .${device.cpu}
|
||
% end
|
||
case .simulator(let model): return model.cpu
|
||
case .unknown: return .unknown
|
||
}
|
||
#elseif os(tvOS)
|
||
switch self {
|
||
% for device in tvOSDevices:
|
||
case .${device.caseName}: return .${device.cpu}
|
||
% end
|
||
case .simulator(let model): return model.cpu
|
||
case .unknown: return .unknown
|
||
}
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return .unknown
|
||
#else
|
||
return .unknown
|
||
#endif
|
||
}
|
||
}
|
||
|
||
extension Device.CPU: CustomStringConvertible {
|
||
|
||
/// A textual representation of the device.
|
||
public var description: String {
|
||
#if os(iOS) || os(tvOS)
|
||
switch self {
|
||
% for cpu in iOS_cpus:
|
||
case .${cpu.name}: return "${cpu.description}"
|
||
% end
|
||
case .unknown: return "unknown"
|
||
}
|
||
#elseif os(watchOS)
|
||
switch self {
|
||
% for cpu in watchOS_cpus:
|
||
case .${cpu.name}: return "${cpu.description}"
|
||
% end
|
||
case .unknown: return "unknown"
|
||
}
|
||
#elseif os(visionOS)
|
||
// TODO: Replace with proper implementation for visionOS.
|
||
return "unknown"
|
||
#else
|
||
return "unknown"
|
||
#endif
|
||
}
|
||
}
|