diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3305fb..2be319a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ ## Unreleased +### New September 2026 devices + +This version adds support for iPhone 18 Pro, iPhone 18 Pro Max, Apple Watch Series 12 and Apple Watch Ultra 4, including hardware identifiers, display metrics and technical specification links: ([#512](https://github.com/devicekit/DeviceKit/pull/512)) + +| Device | Case value | +| --- | --- | +| iPhone 18 Pro | `Device.iPhone18Pro` | +| iPhone 18 Pro Max | `Device.iPhone18ProMax` | +| Apple Watch Series 12 42mm | `Device.appleWatchSeries12_42mm` | +| Apple Watch Series 12 46mm | `Device.appleWatchSeries12_46mm` | +| Apple Watch Ultra 4 | `Device.appleWatchUltra4` | + ### New features - Add `allDevicesWithEsimSupport` / `hasEsimSupport` and `allDevicesWithDualEsimSupport` / `hasDualEsimSupport`, including simulator support. Cover supported iPhones through iPhone 17e and iPads through iPad Air (M4) and iPad Pro (M5), exclude iPhone X, and document regional and Wi-Fi + Cellular limitations. ([#382](https://github.com/devicekit/DeviceKit/pull/382)) diff --git a/Source/Device.generated.swift b/Source/Device.generated.swift index 4aa90682..1fc55345 100644 --- a/Source/Device.generated.swift +++ b/Source/Device.generated.swift @@ -203,61 +203,39 @@ public enum Device { /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP875/sp875-sp876-iphone14-pro-promax_2x.png) case iPhone14ProMax /// Device is an [iPhone 15](https://support.apple.com/kb/SP901) - /// - /// ![Image]() case iPhone15 /// Device is an [iPhone 15 Plus](https://support.apple.com/kb/SP902) - /// - /// ![Image]() case iPhone15Plus /// Device is an [iPhone 15 Pro](https://support.apple.com/kb/SP903) - /// - /// ![Image]() case iPhone15Pro /// Device is an [iPhone 15 Pro Max](https://support.apple.com/kb/SP904) - /// - /// ![Image]() case iPhone15ProMax /// Device is an [iPhone 16](https://support.apple.com/121029) - /// - /// ![Image]() case iPhone16 /// Device is an [iPhone 16 Plus](https://support.apple.com/121030) - /// - /// ![Image]() case iPhone16Plus /// Device is an [iPhone 16 Pro](https://support.apple.com/121031) - /// - /// ![Image]() case iPhone16Pro /// Device is an [iPhone 16 Pro Max](https://support.apple.com/121032) - /// - /// ![Image]() case iPhone16ProMax /// Device is an [iPhone 16e](https://support.apple.com/122208) /// /// ![Image](https://cdsassets.apple.com/live/7WUAS350/images/tech-specs/122208-iphone-16e.png) case iPhone16e /// Device is an [iPhone 17](https://support.apple.com/125089) - /// - /// ![Image]() case iPhone17 /// Device is an [iPhone 17 Pro](https://support.apple.com/125090) - /// - /// ![Image]() case iPhone17Pro /// Device is an [iPhone 17 Pro Max](https://support.apple.com/125091) - /// - /// ![Image]() case iPhone17ProMax /// Device is an [iPhone Air](https://support.apple.com/125092) - /// - /// ![Image]() case iPhoneAir /// Device is an [iPhone 17e](https://support.apple.com/126470) - /// - /// ![Image]() case iPhone17e + /// Device is an [iPhone 18 Pro](https://support.apple.com/en-us/148590) + case iPhone18Pro + /// Device is an [iPhone 18 Pro Max](https://support.apple.com/en-us/148591) + case iPhone18ProMax /// Device is an [iPad 2](https://support.apple.com/kb/SP622) /// /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png) @@ -307,8 +285,6 @@ public enum Device { /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP884/sp884-ipad-10gen-960_2x.png) case iPad10 /// Device is an [iPad (A16)](https://support.apple.com/122240) - /// - /// ![Image]() case iPadA16 /// Device is an [iPad Air (4th generation)](https://support.apple.com/kb/SP828) /// @@ -335,12 +311,8 @@ public enum Device { /// ![Image](https://cdsassets.apple.com/content/services/pub/image?productid=301029&size=240x240) case iPadAir13M3 /// Device is an [iPad Air 11-inch (M4)](https://support.apple.com/126471) - /// - /// ![Image]() case iPadAir11M4 /// Device is an [iPad Air 13-inch (M4)](https://support.apple.com/126472) - /// - /// ![Image]() case iPadAir13M4 /// Device is an [iPad mini](https://support.apple.com/kb/SP661) /// @@ -549,45 +521,31 @@ public enum Device { /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP879/apple-watch-ultra_2x.png) case appleWatchUltra /// Device is an [Apple Watch Series 9](https://support.apple.com/kb/SP905) - /// - /// ![Image]() case appleWatchSeries9_41mm /// Device is an [Apple Watch Series 9](https://support.apple.com/kb/SP905) - /// - /// ![Image]() case appleWatchSeries9_45mm /// Device is an [Apple Watch Ultra2]() - /// - /// ![Image]() case appleWatchUltra2 /// Device is an [Apple Watch SE (3rd generation)]() - /// - /// ![Image]() case appleWatchSE3_40mm /// Device is an [Apple Watch SE (3rd generation)]() - /// - /// ![Image]() case appleWatchSE3_44mm /// Device is an [Apple Watch Series 10]() - /// - /// ![Image]() case appleWatchSeries10_42mm /// Device is an [Apple Watch Series 10]() - /// - /// ![Image]() case appleWatchSeries10_46mm /// Device is an [Apple Watch Ultra 3]() - /// - /// ![Image]() case appleWatchUltra3 /// Device is an [Apple Watch Series 11]() - /// - /// ![Image]() case appleWatchSeries11_42mm /// Device is an [Apple Watch Series 11]() - /// - /// ![Image]() case appleWatchSeries11_46mm + /// Device is an [Apple Watch Series 12 42mm](https://support.apple.com/en-us/148589) + case appleWatchSeries12_42mm + /// Device is an [Apple Watch Series 12 46mm](https://support.apple.com/en-us/148589) + case appleWatchSeries12_46mm + /// Device is an [Apple Watch Ultra 4](https://support.apple.com/en-us/148758) + case appleWatchUltra4 #endif /// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html) @@ -678,6 +636,8 @@ public enum Device { case "iPhone18,2": return iPhone17ProMax case "iPhone18,4": return iPhoneAir case "iPhone18,5": return iPhone17e + case "iPhone19,2": return iPhone18Pro + case "iPhone19,3", "iPhone19,7": return iPhone18ProMax case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return iPad2 case "iPad3,1", "iPad3,2", "iPad3,3": return iPad3 case "iPad3,4", "iPad3,5", "iPad3,6": return iPad4 @@ -770,6 +730,9 @@ public enum Device { case "Watch7,12": return appleWatchUltra3 case "Watch7,17", "Watch7,19": return appleWatchSeries11_42mm case "Watch7,18", "Watch7,20": return appleWatchSeries11_46mm + case "Watch8,2", "Watch8,4": return appleWatchSeries12_42mm + case "Watch8,3", "Watch8,5": return appleWatchSeries12_46mm + case "Watch8,1": return appleWatchUltra4 case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "watchOS")) default: return unknown(identifier) } @@ -853,6 +816,8 @@ public enum Device { case .iPhone17ProMax: return 6.9 case .iPhoneAir: return 6.5 case .iPhone17e: return 6.1 + case .iPhone18Pro: return 6.3 + case .iPhone18ProMax: return 6.9 case .iPad2: return 9.7 case .iPad3: return 9.7 case .iPad4: return 9.7 @@ -936,6 +901,9 @@ public enum Device { case .appleWatchUltra3: return 2.2 case .appleWatchSeries11_42mm: return 1.9 case .appleWatchSeries11_46mm: return 2.0 + case .appleWatchSeries12_42mm: return 1.79 + case .appleWatchSeries12_46mm: return 1.99 + case .appleWatchUltra4: return 2.04 case .simulator(let model): return model.diagonal case .unknown: return -1 } @@ -999,6 +967,8 @@ public enum Device { case .iPhone17ProMax: return (width: 9, height: 19.5) case .iPhoneAir: return (width: 9, height: 19.5) case .iPhone17e: return (width: 9, height: 19.5) + case .iPhone18Pro: return (width: 9, height: 19.5) + case .iPhone18ProMax: return (width: 9, height: 19.5) case .iPad2: return (width: 3, height: 4) case .iPad3: return (width: 3, height: 4) case .iPad4: return (width: 3, height: 4) @@ -1082,6 +1052,9 @@ public enum Device { case .appleWatchUltra3: return (width: 4, height: 5) case .appleWatchSeries11_42mm: return (width: 374, height: 446) case .appleWatchSeries11_46mm: return (width: 416, height: 496) + case .appleWatchSeries12_42mm: return (width: 374, height: 446) + case .appleWatchSeries12_46mm: return (width: 416, height: 496) + case .appleWatchUltra4: return (width: 422, height: 514) case .simulator(let model): return model.screenRatio case .unknown: return (width: -1, height: -1) } @@ -1100,7 +1073,7 @@ public enum Device { /// All iPhones public static var allPhones: [Device] { - return [.iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + return [.iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax] } /// All iPads @@ -1111,17 +1084,17 @@ public enum Device { /// All X-Series Devices @available(*, deprecated, renamed: "allDevicesWithSensorHousing") public static var allXSeriesDevices: [Device] { - return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax] } /// All Plus and Max-Sized Devices public static var allPlusSizedDevices: [Device] { - return [.iPhone6Plus, .iPhone6sPlus, .iPhone7Plus, .iPhone8Plus, .iPhoneXSMax, .iPhone11ProMax, .iPhone12ProMax, .iPhone13ProMax, .iPhone14Plus, .iPhone14ProMax, .iPhone15Plus, .iPhone15ProMax, .iPhone16Plus, .iPhone16ProMax, .iPhone17ProMax, .iPhoneAir] + return [.iPhone6Plus, .iPhone6sPlus, .iPhone7Plus, .iPhone8Plus, .iPhoneXSMax, .iPhone11ProMax, .iPhone12ProMax, .iPhone13ProMax, .iPhone14Plus, .iPhone14ProMax, .iPhone15Plus, .iPhone15ProMax, .iPhone16Plus, .iPhone16ProMax, .iPhone17ProMax, .iPhoneAir, .iPhone18ProMax] } /// All Pro Devices public static var allProDevices: [Device] { - return [.iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, .iPhone18Pro, .iPhone18ProMax, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// All mini Devices @@ -1207,12 +1180,12 @@ public enum Device { /// All Face ID Capable Devices public static var allFaceIDCapableDevices: [Device] { - return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// All Devices with Touch ID or Face ID public static var allBiometricAuthenticationCapableDevices: [Device] { - return [.iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether or not the device has Touch ID @@ -1232,7 +1205,7 @@ public enum Device { /// All devices that feature a sensor housing in the screen public static var allDevicesWithSensorHousing: [Device] { - return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax] } /// All simulator devices that feature a sensor housing in the screen @@ -1247,7 +1220,7 @@ public enum Device { /// All devices that feature a screen with rounded corners. public static var allDevicesWithRoundedDisplayCorners: [Device] { - return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether or not the device has a screen with rounded corners. @@ -1257,7 +1230,7 @@ public enum Device { /// All devices that have the Dynamic Island. public static var allDevicesWithDynamicIsland: [Device] { - return [.iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir] + return [.iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone18Pro, .iPhone18ProMax] } /// Returns whether or not the device has the Dynamic Island. @@ -1277,7 +1250,7 @@ public enum Device { /// All devices that support wireless charging. public static var allDevicesWithWirelessChargingSupport: [Device] { - return [.iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + return [.iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax] } /// Returns whether or not the device supports wireless charging. @@ -1287,7 +1260,7 @@ public enum Device { /// All devices that support 5G. public static var allDevicesWith5gSupport: [Device] { - return [.iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPad10, .iPadA16, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPad10, .iPadA16, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether or not the device has 5G support. @@ -1302,7 +1275,7 @@ public enum Device { /// model capabilities and does not guarantee eSIM availability on a particular device. /// See https://support.apple.com/en-us/109317 and https://support.apple.com/en-us/119592. public static var allDevicesWithEsimSupport: [Device] { - return [.iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether the device model supports eSIM. Simulators use their simulated model. @@ -1315,7 +1288,7 @@ public enum Device { /// Support varies by country, region, and carrier; model membership does not guarantee /// eSIM availability on a particular device. These models also appear in `allDevicesWithEsimSupport`. public static var allDevicesWithDualEsimSupport: [Device] { - return [.iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + return [.iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax] } /// Returns whether the device model supports two active eSIMs simultaneously. @@ -1326,7 +1299,7 @@ public enum Device { /// All devices that have a LiDAR sensor. public static var allDevicesWithALidarSensor: [Device] { - return [.iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, .iPhone18Pro, .iPhone18ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether or not the device has a LiDAR sensor. @@ -1336,7 +1309,7 @@ public enum Device { /// All devices that have a USB-C connectivity. public static var allDevicesWithUSBCConnectivity: [Device] { - return [.iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini6, .iPadMiniA17Pro, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// Returns whether or not the device has a USB-C power supply. @@ -1356,7 +1329,7 @@ public enum Device { #elseif os(watchOS) /// All Watches public static var allWatches: [Device] { - return [.appleWatchSeries0_38mm, .appleWatchSeries0_42mm, .appleWatchSeries1_38mm, .appleWatchSeries1_42mm, .appleWatchSeries2_38mm, .appleWatchSeries2_42mm, .appleWatchSeries3_38mm, .appleWatchSeries3_42mm, .appleWatchSeries4_40mm, .appleWatchSeries4_44mm, .appleWatchSeries5_40mm, .appleWatchSeries5_44mm, .appleWatchSeries6_40mm, .appleWatchSeries6_44mm, .appleWatchSE_40mm, .appleWatchSE_44mm, .appleWatchSeries7_41mm, .appleWatchSeries7_45mm, .appleWatchSeries8_41mm, .appleWatchSeries8_45mm, .appleWatchSE2_40mm, .appleWatchSE2_44mm, .appleWatchUltra, .appleWatchSeries9_41mm, .appleWatchSeries9_45mm, .appleWatchUltra2, .appleWatchSE3_40mm, .appleWatchSE3_44mm, .appleWatchSeries10_42mm, .appleWatchSeries10_46mm, .appleWatchUltra3, .appleWatchSeries11_42mm, .appleWatchSeries11_46mm] + return [.appleWatchSeries0_38mm, .appleWatchSeries0_42mm, .appleWatchSeries1_38mm, .appleWatchSeries1_42mm, .appleWatchSeries2_38mm, .appleWatchSeries2_42mm, .appleWatchSeries3_38mm, .appleWatchSeries3_42mm, .appleWatchSeries4_40mm, .appleWatchSeries4_44mm, .appleWatchSeries5_40mm, .appleWatchSeries5_44mm, .appleWatchSeries6_40mm, .appleWatchSeries6_44mm, .appleWatchSE_40mm, .appleWatchSE_44mm, .appleWatchSeries7_41mm, .appleWatchSeries7_45mm, .appleWatchSeries8_41mm, .appleWatchSeries8_45mm, .appleWatchSE2_40mm, .appleWatchSE2_44mm, .appleWatchUltra, .appleWatchSeries9_41mm, .appleWatchSeries9_45mm, .appleWatchUltra2, .appleWatchSE3_40mm, .appleWatchSE3_44mm, .appleWatchSeries10_42mm, .appleWatchSeries10_46mm, .appleWatchUltra3, .appleWatchSeries11_42mm, .appleWatchSeries11_46mm, .appleWatchSeries12_42mm, .appleWatchSeries12_46mm, .appleWatchUltra4] } /// All simulator Watches @@ -1576,6 +1549,8 @@ public enum Device { case .iPhone17ProMax: return 460 case .iPhoneAir: return 460 case .iPhone17e: return 460 + case .iPhone18Pro: return 460 + case .iPhone18ProMax: return 460 case .iPad2: return 132 case .iPad3: return 264 case .iPad4: return 264 @@ -1659,6 +1634,9 @@ public enum Device { case .appleWatchUltra3: return 338 case .appleWatchSeries11_42mm: return 326 case .appleWatchSeries11_46mm: return 326 + case .appleWatchSeries12_42mm: return 326 + case .appleWatchSeries12_46mm: return 326 + case .appleWatchUltra4: return 326 case .simulator(let model): return model.ppi case .unknown: return nil } @@ -1754,6 +1732,8 @@ extension Device: CustomStringConvertible { case .iPhone17ProMax: return "iPhone 17 Pro Max" case .iPhoneAir: return "iPhone Air" case .iPhone17e: return "iPhone 17e" + case .iPhone18Pro: return "iPhone 18 Pro" + case .iPhone18ProMax: return "iPhone 18 Pro Max" case .iPad2: return "iPad 2" case .iPad3: return "iPad (3rd generation)" case .iPad4: return "iPad (4th generation)" @@ -1837,6 +1817,9 @@ extension Device: CustomStringConvertible { case .appleWatchUltra3: return "Apple Watch Ultra 3" case .appleWatchSeries11_42mm: return "Apple Watch Series 11 42mm" case .appleWatchSeries11_46mm: return "Apple Watch Series 11 46mm" + case .appleWatchSeries12_42mm: return "Apple Watch Series 12 42mm" + case .appleWatchSeries12_46mm: return "Apple Watch Series 12 46mm" + case .appleWatchUltra4: return "Apple Watch Ultra 4" case .simulator(let model): return "Simulator (\(model.description))" case .unknown(let identifier): return identifier } @@ -1919,6 +1902,8 @@ extension Device: CustomStringConvertible { case .iPhone17ProMax: return "iPhone 17 Pro Max" case .iPhoneAir: return "iPhone Air" case .iPhone17e: return "iPhone 17e" + case .iPhone18Pro: return "iPhone 18 Pro" + case .iPhone18ProMax: return "iPhone 18 Pro Max" case .iPad2: return "iPad 2" case .iPad3: return "iPad (3rd generation)" case .iPad4: return "iPad (4th generation)" @@ -2002,6 +1987,9 @@ extension Device: CustomStringConvertible { case .appleWatchUltra3: return "Apple Watch Ultra 3" case .appleWatchSeries11_42mm: return "Apple Watch Series 11 42mm" case .appleWatchSeries11_46mm: return "Apple Watch Series 11 46mm" + case .appleWatchSeries12_42mm: return "Apple Watch Series 12 42mm" + case .appleWatchSeries12_46mm: return "Apple Watch Series 12 46mm" + case .appleWatchUltra4: return "Apple Watch Ultra 4" case .simulator(let model): return "Simulator (\(model.safeDescription))" case .unknown(let identifier): return identifier } @@ -2441,13 +2429,15 @@ extension Device { case .iPhone16ProMax: return [.wide, .telephoto, .ultraWide] case .iPhone17Pro: return [.wide, .telephoto, .ultraWide] case .iPhone17ProMax: return [.wide, .telephoto, .ultraWide] + case .iPhone18Pro: return [.wide, .telephoto, .ultraWide] + case .iPhone18ProMax: return [.wide, .telephoto, .ultraWide] default: return [] } } /// All devices that feature a camera public static var allDevicesWithCamera: [Device] { - return [.iPodTouch5, .iPodTouch6, .iPodTouch7, .iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPodTouch5, .iPodTouch6, .iPodTouch7, .iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// All devices that feature a normal camera @@ -2458,17 +2448,17 @@ extension Device { /// All devices that feature a wide camera public static var allDevicesWithWideCamera: [Device] { - return [.iPodTouch5, .iPodTouch6, .iPodTouch7, .iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] + return [.iPodTouch5, .iPodTouch6, .iPodTouch7, .iPhone4, .iPhone4s, .iPhone5, .iPhone5c, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e, .iPhone18Pro, .iPhone18ProMax, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPad9, .iPad10, .iPadA16, .iPadAir4, .iPadAir5, .iPadAir11M2, .iPadAir13M2, .iPadAir11M3, .iPadAir13M3, .iPadAir11M4, .iPadAir13M4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadMini6, .iPadMiniA17Pro, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6, .iPadPro11M4, .iPadPro13M4, .iPadPro11M5, .iPadPro13M5] } /// All devices that feature a telephoto camera public static var allDevicesWithTelephotoCamera: [Device] { - return [.iPhone7Plus, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax] + return [.iPhone7Plus, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax, .iPhone15Pro, .iPhone15ProMax, .iPhone16Pro, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, .iPhone18Pro, .iPhone18ProMax] } /// All devices that feature an ultra wide camera public static var allDevicesWithUltraWideCamera: [Device] { - return [.iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6] + return [.iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhone14, .iPhone14Plus, .iPhone14Pro, .iPhone14ProMax, .iPhone15, .iPhone15Plus, .iPhone15Pro, .iPhone15ProMax, .iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhone18Pro, .iPhone18ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5, .iPadPro11Inch4, .iPadPro12Inch6] } /// Returns whether or not the current device has a camera @@ -2563,6 +2553,7 @@ extension Device { case a18Pro case a19 case a19Pro + case a20Pro case m1 case m2 case m3 @@ -2580,6 +2571,7 @@ extension Device { case s8 case s9 case s10 + case s11 #endif case unknown } @@ -2640,6 +2632,8 @@ extension Device { case .iPhone17ProMax: return .a19Pro case .iPhoneAir: return .a19Pro case .iPhone17e: return .a19 + case .iPhone18Pro: return .a20Pro + case .iPhone18ProMax: return .a20Pro case .iPad2: return .a5 case .iPad3: return .a5X case .iPad4: return .a6X @@ -2723,6 +2717,9 @@ extension Device { case .appleWatchUltra3: return .s10 case .appleWatchSeries11_42mm: return .s10 case .appleWatchSeries11_46mm: return .s10 + case .appleWatchSeries12_42mm: return .s11 + case .appleWatchSeries12_46mm: return .s11 + case .appleWatchUltra4: return .s11 case .simulator(let model): return model.cpu case .unknown: return .unknown } @@ -2775,6 +2772,7 @@ extension Device.CPU: CustomStringConvertible { case .a18Pro: return "A18 Pro" case .a19: return "A19" case .a19Pro: return "A19 Pro" + case .a20Pro: return "A20 Pro" case .m1: return "M1" case .m2: return "M2" case .m3: return "M3" @@ -2795,6 +2793,7 @@ extension Device.CPU: CustomStringConvertible { case .s8: return "S8" case .s9: return "S9" case .s10: return "S10" + case .s11: return "S11" case .unknown: return "unknown" } #elseif os(visionOS) diff --git a/Source/Device.swift.gyb b/Source/Device.swift.gyb index a33cb126..63b4348a 100644 --- a/Source/Device.swift.gyb +++ b/Source/Device.swift.gyb @@ -270,6 +270,20 @@ iPhones = [ supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=1, hasUSBCConnectivity=True, has5gSupport=True, hasEsimSupport=True, hasDualEsimSupport=True), + + # Identifiers: https://api.ipsw.me/v4/devices (verified 2026-09-21). + # iPhone19,3 and iPhone19,7 are regional variants of iPhone 18 Pro Max. + Device("iPhone18Pro", "Device is an [iPhone 18 Pro](https://support.apple.com/en-us/148590)", "", ["iPhone19,2"], 6.3, (9, 19.5), "iPhone 18 Pro", "iPhone 18 Pro", 460, + cpu="a20Pro", isPro=True, isXSeries=True, hasFaceID=True, + hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, + cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), + Device("iPhone18ProMax", "Device is an [iPhone 18 Pro Max](https://support.apple.com/en-us/148591)", "", ["iPhone19,3", "iPhone19,7"], 6.9, (9, 19.5), "iPhone 18 Pro Max", "iPhone 18 Pro Max", 460, + cpu="a20Pro", isPlusFormFactor=True, isPro=True, isXSeries=True, + hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, + hasDynamicIsland=True, cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, + has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), ] iPads = [ @@ -665,6 +679,14 @@ watches = [ ["Watch7,18", "Watch7,20"], 2.0, (416,496), "Apple Watch Series 11 46mm", "Apple Watch Series 11 46mm", 326, cpu="s10", supportsWirelessCharging=True), + # Identifiers: https://gist.github.com/adamawolf/3048717 (verified 2026-09-21). + # Rectangular display diagonals calculated from Apple's pixel dimensions / PPI, rounded to two decimals. + Device("appleWatchSeries12_42mm", "Device is an [Apple Watch Series 12 42mm](https://support.apple.com/en-us/148589)", "", ["Watch8,2", "Watch8,4"], 1.79, (374,446), "Apple Watch Series 12 42mm", "Apple Watch Series 12 42mm", 326, + cpu="s11", supportsWirelessCharging=True), + Device("appleWatchSeries12_46mm", "Device is an [Apple Watch Series 12 46mm](https://support.apple.com/en-us/148589)", "", ["Watch8,3", "Watch8,5"], 1.99, (416,496), "Apple Watch Series 12 46mm", "Apple Watch Series 12 46mm", 326, + cpu="s11", supportsWirelessCharging=True), + Device("appleWatchUltra4", "Device is an [Apple Watch Ultra 4](https://support.apple.com/en-us/148758)", "", ["Watch8,1"], 2.04, (422,514), "Apple Watch Ultra 4", "Apple Watch Ultra 4", 326, + cpu="s11", supportsWirelessCharging=True), ] iOSDevices = iPods + iPhones + iPads + homePods @@ -714,22 +736,28 @@ public enum Device { #if os(iOS) % for device in iOSDevices: /// ${device.comment} +% if device.imageURL: /// /// ![Image](${device.imageURL}) +% end case ${device.caseName} % end #elseif os(tvOS) % for device in tvOSDevices: /// ${device.comment} +% if device.imageURL: /// /// ![Image](${device.imageURL}) +% end case ${device.caseName} % end #elseif os(watchOS) % for device in watchOSDevices: /// ${device.comment} +% if device.imageURL: /// /// ![Image](${device.imageURL}) +% end case ${device.caseName} % end #endif @@ -1881,6 +1909,7 @@ iOS_cpus = [ CPU("a18Pro" , "A18 Pro"), CPU("a19" , "A19"), CPU("a19Pro" , "A19 Pro"), + CPU("a20Pro" , "A20 Pro"), CPU("m1", "M1"), CPU("m2", "M2"), CPU("m3", "M3"), @@ -1900,6 +1929,7 @@ watchOS_cpus = [ CPU("s8", "S8"), CPU("s9", "S9"), CPU("s10", "S10"), + CPU("s11", "S11"), ] }% diff --git a/Tests/Tests.swift b/Tests/Tests.swift index 37561bc8..ce99bbc6 100644 --- a/Tests/Tests.swift +++ b/Tests/Tests.swift @@ -16,6 +16,65 @@ class DeviceKitTests: XCTestCase { let device = Device.current + #if os(iOS) || os(watchOS) + func testSeptember2026Devices() { + struct ExpectedDevice { + let model: Device + let identifiers: [String] + let diagonal: Double + let ratio: (Double, Double) + let ppi: Int + } + #if os(iOS) + let models: [ExpectedDevice] = [ + ExpectedDevice(model: .iPhone18Pro, identifiers: ["iPhone19,2"], diagonal: 6.3, ratio: (9, 19.5), ppi: 460), + ExpectedDevice(model: .iPhone18ProMax, identifiers: ["iPhone19,3", "iPhone19,7"], diagonal: 6.9, ratio: (9, 19.5), ppi: 460) + ] + let chip = Device.CPU.a20Pro + XCTAssertEqual(chip.description, "A20 Pro") + // The deferred model and unverified identifiers must remain unknown. + for identifier in ["iPhone19,1", "iPhone19,4", "iPhone19,5", "iPhone19,6", "placeholder:iPhone18Pro", "placeholder:iPhone18ProMax"] { + XCTAssertEqual(Device.mapToDevice(identifier: identifier), .unknown(identifier)) + } + #else + let models: [ExpectedDevice] = [ + ExpectedDevice(model: .appleWatchSeries12_42mm, identifiers: ["Watch8,2", "Watch8,4"], diagonal: 1.79, ratio: (374, 446), ppi: 326), + ExpectedDevice(model: .appleWatchSeries12_46mm, identifiers: ["Watch8,3", "Watch8,5"], diagonal: 1.99, ratio: (416, 496), ppi: 326), + ExpectedDevice(model: .appleWatchUltra4, identifiers: ["Watch8,1"], diagonal: 2.04, ratio: (422, 514), ppi: 326) + ] + let chip = Device.CPU.s11 + XCTAssertEqual(chip.description, "S11") + for identifier in ["Watch8,6", "Watch8,7", "Watch8,8", "Watch8,9", "placeholder:appleWatchSeries12_42mm", "placeholder:appleWatchSeries12_46mm", "placeholder:appleWatchUltra4"] { + XCTAssertEqual(Device.mapToDevice(identifier: identifier), .unknown(identifier)) + } + #endif + for expected in models { + let model = expected.model + for identifier in expected.identifiers { + XCTAssertEqual(Device.mapToDevice(identifier: identifier), model, identifier) + } + #if os(iOS) + XCTAssertTrue(model.isPhone) + XCTAssertFalse(model.isPad) + #endif + XCTAssertTrue(Device.allRealDevices.contains(model)) + XCTAssertTrue(Device.allSimulators.contains(.simulator(model))) + for variant in [model, .simulator(model)] { + XCTAssertEqual(variant.cpu, chip) + XCTAssertEqual(variant.diagonal, expected.diagonal) + XCTAssertEqual(variant.screenRatio.width, expected.ratio.0) + XCTAssertEqual(variant.screenRatio.height, expected.ratio.1) + XCTAssertEqual(variant.ppi, expected.ppi) + #if os(iOS) + XCTAssertTrue(variant.supportsWirelessCharging) + XCTAssertTrue(variant.hasEsimSupport) + XCTAssertTrue(variant.hasDualEsimSupport) + #endif + } + } + } + #endif + func testDeviceSimulator() { #if os(macOS) XCTAssertFalse(device.isOneOf(Device.allSimulators)) @@ -475,6 +534,7 @@ class DeviceKitTests: XCTestCase { .iPhone16ProMax, .iPhone17ProMax, .iPhoneAir, + .iPhone18ProMax, ]) } @@ -494,6 +554,8 @@ class DeviceKitTests: XCTestCase { .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, + .iPhone18Pro, + .iPhone18ProMax, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, @@ -544,6 +606,8 @@ class DeviceKitTests: XCTestCase { .iPhone17, .iPhone17Pro, .iPhone17ProMax, + .iPhone18Pro, + .iPhone18ProMax, .iPhoneAir, ] for device in Device.allRealDevices { @@ -578,6 +642,8 @@ class DeviceKitTests: XCTestCase { .iPhone17, .iPhone17Pro, .iPhone17ProMax, + .iPhone18Pro, + .iPhone18ProMax, .iPhoneAir, .iPhone17e, .iPad10, @@ -722,6 +788,8 @@ class DeviceKitTests: XCTestCase { .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax, + .iPhone18Pro, + .iPhone18ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, @@ -752,6 +820,8 @@ class DeviceKitTests: XCTestCase { .iPhone17, .iPhone17Pro, .iPhone17ProMax, + .iPhone18Pro, + .iPhone18ProMax, .iPhoneAir, .iPhone17e, .iPad10,