diff --git a/CHANGELOG.md b/CHANGELOG.md index 03602d0c..d384fa2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +### 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)) + +Thanks to [furiosFast](https://github.com/furiosFast) for the original eSIM support contribution! + ### Maintenance - Simplify GYB device definitions with named feature parameters and defaults for unsupported features, preserving the generated Swift output. ([#508](https://github.com/devicekit/DeviceKit/pull/508)) diff --git a/Source/Device.generated.swift b/Source/Device.generated.swift index bd5a0638..ad060846 100644 --- a/Source/Device.generated.swift +++ b/Source/Device.generated.swift @@ -1295,6 +1295,35 @@ public enum Device { return isOneOf(Device.allDevicesWith5gSupport) || isOneOf(Device.allDevicesWith5gSupport.map(Device.simulator)) } + /// All iPhone and iPad models that support at least one active eSIM, including dual eSIM models. + /// + /// Support varies by country, region, and carrier. For iPad, only Wi-Fi + Cellular variants + /// support eSIM. Device cases do not distinguish these variants, so membership describes + /// 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] + } + + /// Returns whether the device model supports eSIM. Simulators use their simulated model. + /// See `allDevicesWithEsimSupport` for regional and cellular-variant limitations. + public var hasEsimSupport: Bool { + return isOneOf(Device.allDevicesWithEsimSupport) || isOneOf(Device.allDevicesWithEsimSupport.map(Device.simulator)) + } + + /// All iPhone models that support two active eSIMs simultaneously. + /// 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] + } + + /// Returns whether the device model supports two active eSIMs simultaneously. + /// Simulators use their simulated model. See `allDevicesWithDualEsimSupport` for limitations. + public var hasDualEsimSupport: Bool { + return isOneOf(Device.allDevicesWithDualEsimSupport) || isOneOf(Device.allDevicesWithDualEsimSupport.map(Device.simulator)) + } + /// 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] diff --git a/Source/Device.swift.gyb b/Source/Device.swift.gyb index 7a61e94a..fc753ea2 100644 --- a/Source/Device.swift.gyb +++ b/Source/Device.swift.gyb @@ -30,6 +30,8 @@ class Device: hasLidarSensor=False, hasUSBCConnectivity=False, has5gSupport=False, + hasEsimSupport=False, + hasDualEsimSupport=False, ): self.caseName = caseName self.comment = comment @@ -57,6 +59,8 @@ class Device: self.cpu = cpu self.hasUSBCConnectivity = hasUSBCConnectivity self.has5gSupport = has5gSupport + self.hasEsimSupport = hasEsimSupport + self.hasDualEsimSupport = hasDualEsimSupport # iOS iPods = [ @@ -107,131 +111,165 @@ iPhones = [ 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, cpu="a12Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasForce3dTouchSupport=True, - cameras=12), + cameras=12, + hasEsimSupport=True), 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, cpu="a12Bionic", isPlusFormFactor=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - hasForce3dTouchSupport=True, cameras=12), + hasForce3dTouchSupport=True, cameras=12, + hasEsimSupport=True), 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, cpu="a12Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=1), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=1, + hasEsimSupport=True), 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, cpu="a13Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, + hasEsimSupport=True), 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, cpu="a13Bionic", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=123), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=123, + hasEsimSupport=True), 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, cpu="a13Bionic", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - cameras=123), + cameras=123, + hasEsimSupport=True), 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, - cpu="a13Bionic", hasTouchID=True, supportsWirelessCharging=True, cameras=1), + cpu="a13Bionic", hasTouchID=True, supportsWirelessCharging=True, cameras=1, + hasEsimSupport=True), 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, cpu="a14Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True, + hasEsimSupport=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, cpu="a14Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True, + hasEsimSupport=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, cpu="a14Bionic", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=123, - hasLidarSensor=True, has5gSupport=True), + hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=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, cpu="a14Bionic", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - cameras=123, hasLidarSensor=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=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, cpu="a15Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=123, - hasLidarSensor=True, has5gSupport=True), + hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - cameras=123, hasLidarSensor=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", hasTouchID=True, supportsWirelessCharging=True, cameras=1, - has5gSupport=True), + has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, - supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True), + supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=13, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a15Bionic", isPlusFormFactor=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - cameras=13, has5gSupport=True), + cameras=13, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a16Bionic", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=123, hasLidarSensor=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a16Bionic", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - hasDynamicIsland=True, cameras=123, hasLidarSensor=True, has5gSupport=True), + hasDynamicIsland=True, cameras=123, hasLidarSensor=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a16Bionic", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=13, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a16Bionic", isPlusFormFactor=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, - hasDynamicIsland=True, cameras=13, hasUSBCConnectivity=True, has5gSupport=True), + hasDynamicIsland=True, cameras=13, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a17Pro", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a17Pro", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, - has5gSupport=True), + has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone16", "Device is an [iPhone 16]()", "", ["iPhone17,3"], 6.1, (9, 19.5), "iPhone 16", "iPhone 16", 460, cpu="a18", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=13, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone16Plus", "Device is an [iPhone 16 Plus]()", "", ["iPhone17,4"], 6.7, (9, 19.5), "iPhone 16 Plus", "iPhone 16 Plus", 460, cpu="a18", isPlusFormFactor=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=13, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone16Pro", "Device is an [iPhone 16 Pro]()", "", ["iPhone17,1"], 6.3, (9, 19.5), "iPhone 16 Pro", "iPhone 16 Pro", 460, cpu="a18Pro", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a18Pro", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, - has5gSupport=True), + has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a18", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone17", "Device is an [iPhone 17]()", "", ["iPhone18,3"], 6.3, (9, 19.5), "iPhone 17", "iPhone 17", 460, cpu="a19", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=13, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone17Pro", "Device is an [iPhone 17 Pro]()", "", ["iPhone18,1"], 6.3, (9, 19.5), "iPhone 17 Pro", "iPhone 17 Pro", 460, cpu="a19Pro", isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=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, cpu="a19Pro", isPlusFormFactor=True, isPro=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, cameras=123, hasLidarSensor=True, hasUSBCConnectivity=True, - has5gSupport=True), + has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhoneAir", "Device is an [iPhone Air]()", "", ["iPhone18,4"], 6.5, (9, 19.5), "iPhone Air", "iPhone Air", 460, cpu="a19Pro", isPlusFormFactor=True, isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, hasDynamicIsland=True, - cameras=1, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), Device("iPhone17e", "Device is an [iPhone 17e]()", "", ["iPhone18,5"], 6.1, (9, 19.5), "iPhone 17e", "iPhone 17e", 460, cpu="a19", isXSeries=True, hasFaceID=True, hasSensorHousing=True, supportsWirelessCharging=True, hasRoundedDisplayCorners=True, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True, hasDualEsimSupport=True), ] iPads = [ @@ -250,43 +288,57 @@ iPads = [ 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, cpu="a10Fusion", hasTouchID=True, applePencilSupport=1, cameras=1), 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, - cpu="a12Bionic", hasTouchID=True, applePencilSupport=1, cameras=1), + cpu="a12Bionic", hasTouchID=True, applePencilSupport=1, cameras=1, + hasEsimSupport=True), 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, - cpu="a10Fusion", hasTouchID=True, applePencilSupport=1, cameras=1), + cpu="a10Fusion", hasTouchID=True, applePencilSupport=1, cameras=1, + hasEsimSupport=True), 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, - cpu="a12Bionic", hasTouchID=True, applePencilSupport=1, cameras=1), + cpu="a12Bionic", hasTouchID=True, applePencilSupport=1, cameras=1, + hasEsimSupport=True), 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, - cpu="a13Bionic", hasTouchID=True, applePencilSupport=1, cameras=1), + cpu="a13Bionic", hasTouchID=True, applePencilSupport=1, cameras=1, + hasEsimSupport=True), 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, cpu="a14Bionic", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=13, - cameras=1, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True), Device("iPadA16", "Device is an [iPad (A16)]()", "", ["iPad15,7", "iPad15,8"], 10.9, (41, 59), "iPad (A16)", "iPad (A16)", 264, cpu="a16Bionic", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=13, - cameras=1, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="a14Bionic", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, - cameras=1, hasUSBCConnectivity=True), + cameras=1, hasUSBCConnectivity=True, + hasEsimSupport=True), 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, cpu="m1", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m2", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m2", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m3", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m3", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m4", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m4", hasTouchID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, cameras=1, - hasUSBCConnectivity=True, has5gSupport=True), + hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="a5", isPadMiniFormFactor=True, cameras=1), 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, @@ -296,13 +348,16 @@ iPads = [ 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, cpu="a8", isPadMiniFormFactor=True, hasTouchID=True, cameras=1), 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, - cpu="a12Bionic", isPadMiniFormFactor=True, hasTouchID=True, applePencilSupport=1, cameras=1), + cpu="a12Bionic", isPadMiniFormFactor=True, hasTouchID=True, applePencilSupport=1, cameras=1, + hasEsimSupport=True), 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, cpu="a15Bionic", isPadMiniFormFactor=True, hasTouchID=True, hasRoundedDisplayCorners=True, - applePencilSupport=23, cameras=1, hasUSBCConnectivity=True, has5gSupport=True), + applePencilSupport=23, cameras=1, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="a17Pro", isPadMiniFormFactor=True, hasTouchID=True, hasRoundedDisplayCorners=True, - applePencilSupport=34, cameras=1, hasUSBCConnectivity=True, has5gSupport=True), + applePencilSupport=34, cameras=1, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="a9X", isPro=True, hasTouchID=True, applePencilSupport=1, cameras=1), 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, @@ -313,40 +368,52 @@ iPads = [ cpu="a10XFusion", isPro=True, hasTouchID=True, applePencilSupport=1, cameras=1), 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, cpu="a12XBionic", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, - applePencilSupport=23, cameras=1, hasUSBCConnectivity=True), + applePencilSupport=23, cameras=1, hasUSBCConnectivity=True, + hasEsimSupport=True), 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, cpu="a12XBionic", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, - applePencilSupport=23, cameras=1, hasUSBCConnectivity=True), + applePencilSupport=23, cameras=1, hasUSBCConnectivity=True, + hasEsimSupport=True), 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, cpu="a12ZBionic", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, - applePencilSupport=23, cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True), + applePencilSupport=23, cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, + hasEsimSupport=True), 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, cpu="a12ZBionic", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, - applePencilSupport=23, cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True), + applePencilSupport=23, cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, + hasEsimSupport=True), 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, cpu="m1", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, - cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m1", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, - cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m2", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, - cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m2", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=23, - cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=13, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m4", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, - cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m4", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=34, - cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m5", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=234, - cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=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, cpu="m5", isPro=True, hasFaceID=True, hasRoundedDisplayCorners=True, applePencilSupport=234, - cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True), + cameras=1, hasLidarSensor=True, hasUSBCConnectivity=True, has5gSupport=True, + hasEsimSupport=True), ] homePods = [ @@ -999,6 +1066,35 @@ public enum Device { return isOneOf(Device.allDevicesWith5gSupport) || isOneOf(Device.allDevicesWith5gSupport.map(Device.simulator)) } + /// All iPhone and iPad models that support at least one active eSIM, including dual eSIM models. + /// + /// Support varies by country, region, and carrier. For iPad, only Wi-Fi + Cellular variants + /// support eSIM. Device cases do not distinguish these variants, so membership describes + /// 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 [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasEsimSupport == True, iOSDevices)))))}] + } + + /// Returns whether the device model supports eSIM. Simulators use their simulated model. + /// See `allDevicesWithEsimSupport` for regional and cellular-variant limitations. + public var hasEsimSupport: Bool { + return isOneOf(Device.allDevicesWithEsimSupport) || isOneOf(Device.allDevicesWithEsimSupport.map(Device.simulator)) + } + + /// All iPhone models that support two active eSIMs simultaneously. + /// 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 [${', '.join(list(map(lambda device: "." + device.caseName, list(filter(lambda device: device.hasDualEsimSupport == True, iOSDevices)))))}] + } + + /// Returns whether the device model supports two active eSIMs simultaneously. + /// Simulators use their simulated model. See `allDevicesWithDualEsimSupport` for limitations. + public var hasDualEsimSupport: Bool { + return isOneOf(Device.allDevicesWithDualEsimSupport) || isOneOf(Device.allDevicesWithDualEsimSupport.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)))))}] diff --git a/Tests/Tests.swift b/Tests/Tests.swift index 1e87af88..37561bc8 100644 --- a/Tests/Tests.swift +++ b/Tests/Tests.swift @@ -605,6 +605,50 @@ class DeviceKitTests: XCTestCase { } } + func testEsimSupportBoundaries() { + // eSIM starts with XS/XR; dual eSIM starts with iPhone 13 and SE (3rd generation). + let unsupported: [Device] = [.iPhoneX, .iPhone8, .iPhoneSE, .iPad6, .iPadAir2, + .iPadMini4, .iPadPro10Inch, .iPadPro12Inch2, .iPodTouch7, + .unknown("future device")] + let esimOnly: [Device] = [.iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhoneSE2, + .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, + .iPad7, .iPadAir3, .iPadMini5, .iPadPro11Inch, .iPadPro12Inch3] + let dualEsim: [Device] = [.iPhone13, .iPhone13Mini, .iPhone13Pro, .iPhone13ProMax, .iPhoneSE3] + for model in unsupported + esimOnly + dualEsim { + for variant in [model, .simulator(model)] { + XCTAssertEqual(variant.hasEsimSupport, !unsupported.contains(model), "\(variant)") + XCTAssertEqual(variant.hasDualEsimSupport, dualEsim.contains(model), "\(variant)") + } + } + } + + func testRecentDevicesEsimSupport() { + let phones: [Device] = [.iPhone16, .iPhone16Plus, .iPhone16Pro, .iPhone16ProMax, .iPhone16e, + .iPhone17, .iPhone17Pro, .iPhone17ProMax, .iPhoneAir, .iPhone17e] + let pads: [Device] = [.iPadAir11M2, .iPadAir13M2, .iPadPro11M4, .iPadPro13M4, + .iPadMiniA17Pro, .iPadA16, .iPadAir11M3, .iPadAir13M3, + .iPadPro11M5, .iPadPro13M5, .iPadAir11M4, .iPadAir13M4] + for model in phones + pads { + for variant in [model, .simulator(model)] { + XCTAssertTrue(variant.hasEsimSupport, "\(variant)") + XCTAssertEqual(variant.hasDualEsimSupport, phones.contains(model), "\(variant)") + } + } + } + + func testEsimDeviceLists() { + for model in Device.allDevicesWithDualEsimSupport { + XCTAssertTrue(Device.allDevicesWithEsimSupport.contains(model), "\(model)") + XCTAssertTrue(model.isPhone) + } + for model in Device.allRealDevices { + XCTAssertEqual(Device.allDevicesWithEsimSupport.contains(model), model.hasEsimSupport) + XCTAssertEqual(Device.allDevicesWithDualEsimSupport.contains(model), model.hasDualEsimSupport) + } + XCTAssertFalse(Device.allDevicesWithEsimSupport.contains(.iPhoneX)) + XCTAssertFalse(Device.allDevicesWithDualEsimSupport.contains(.iPhone12)) + } + // MARK: - volumes @available(iOS 11.0, *) func testVolumeTotalCapacity() {