| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725 |
- //===----------------------------------------------------------------------===//
- //
- // This source file is part of the DeviceKit open source project
- //
- // Copyright © 2014 - 2018 Dennis Weissmann and the DeviceKit project authors
- //
- // License: https://github.com/dennisweissmann/DeviceKit/blob/master/LICENSE
- // Contributors: https://github.com/dennisweissmann/DeviceKit#contributors
- //
- //===----------------------------------------------------------------------===//
- #if os(watchOS)
- import WatchKit
- #else
- import UIKit
- #endif
- // MARK: Device
- /// This enum is a value-type wrapper and extension of
- /// [`UIDevice`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/).
- ///
- /// Usage:
- ///
- /// let device = Device.current
- ///
- /// print(device) // prints, for example, "iPhone 6 Plus"
- ///
- /// if device == .iPhone6Plus {
- /// // Do something
- /// } else {
- /// // Do something else
- /// }
- ///
- /// ...
- ///
- /// if device.batteryState == .full || device.batteryState >= .charging(75) {
- /// print("Your battery is happy! 😊")
- /// }
- ///
- /// ...
- ///
- /// if device.batteryLevel >= 50 {
- /// install_iOS()
- /// } else {
- /// showError()
- /// }
- ///
- public enum Device {
- #if os(iOS)
- /// Device is an [iPod touch (5th generation)](https://support.apple.com/kb/SP657)
- ///
- /// 
- case iPodTouch5
- /// Device is an [iPod touch (6th generation)](https://support.apple.com/kb/SP720)
- ///
- /// 
- case iPodTouch6
- /// Device is an [iPod touch (7th generation)](https://support.apple.com/kb/SP796)
- ///
- /// 
- case iPodTouch7
- /// Device is an [iPhone 4](https://support.apple.com/kb/SP587)
- ///
- /// 
- case iPhone4
- /// Device is an [iPhone 4s](https://support.apple.com/kb/SP643)
- ///
- /// 
- case iPhone4s
- /// Device is an [iPhone 5](https://support.apple.com/kb/SP655)
- ///
- /// 
- case iPhone5
- /// Device is an [iPhone 5c](https://support.apple.com/kb/SP684)
- ///
- /// 
- case iPhone5c
- /// Device is an [iPhone 5s](https://support.apple.com/kb/SP685)
- ///
- /// 
- case iPhone5s
- /// Device is an [iPhone 6](https://support.apple.com/kb/SP705)
- ///
- /// 
- case iPhone6
- /// Device is an [iPhone 6 Plus](https://support.apple.com/kb/SP706)
- ///
- /// 
- case iPhone6Plus
- /// Device is an [iPhone 6s](https://support.apple.com/kb/SP726)
- ///
- /// 
- case iPhone6s
- /// Device is an [iPhone 6s Plus](https://support.apple.com/kb/SP727)
- ///
- /// 
- case iPhone6sPlus
- /// Device is an [iPhone 7](https://support.apple.com/kb/SP743)
- ///
- /// 
- case iPhone7
- /// Device is an [iPhone 7 Plus](https://support.apple.com/kb/SP744)
- ///
- /// 
- case iPhone7Plus
- /// Device is an [iPhone SE](https://support.apple.com/kb/SP738)
- ///
- /// 
- case iPhoneSE
- /// Device is an [iPhone 8](https://support.apple.com/kb/SP767)
- ///
- /// 
- case iPhone8
- /// Device is an [iPhone 8 Plus](https://support.apple.com/kb/SP768)
- ///
- /// 
- case iPhone8Plus
- /// Device is an [iPhone X](https://support.apple.com/kb/SP770)
- ///
- /// 
- case iPhoneX
- /// Device is an [iPhone Xs](https://support.apple.com/kb/SP779)
- ///
- /// 
- case iPhoneXS
- /// Device is an [iPhone Xs Max](https://support.apple.com/kb/SP780)
- ///
- /// 
- case iPhoneXSMax
- /// Device is an [iPhone Xʀ](https://support.apple.com/kb/SP781)
- ///
- /// 
- case iPhoneXR
- /// Device is an [iPhone 11](https://support.apple.com/kb/SP804)
- ///
- /// 
- case iPhone11
- /// Device is an [iPhone 11 Pro](https://support.apple.com/kb/SP805)
- ///
- /// 
- case iPhone11Pro
- /// Device is an [iPhone 11 Pro Max](https://support.apple.com/kb/SP806)
- ///
- /// 
- case iPhone11ProMax
- /// Device is an [iPhone SE (2nd generation)](https://support.apple.com/kb/SP820)
- ///
- /// 
- case iPhoneSE2
- /// Device is an [iPhone 12](https://support.apple.com/kb/SP830)
- ///
- /// 
- case iPhone12
- /// Device is an [iPhone 12 mini](https://support.apple.com/kb/SP829)
- ///
- /// 
- case iPhone12Mini
- /// Device is an [iPhone 12 Pro](https://support.apple.com/kb/SP831)
- ///
- /// 
- case iPhone12Pro
- /// Device is an [iPhone 12 Pro Max](https://support.apple.com/kb/SP832)
- ///
- /// 
- case iPhone12ProMax
- /// Device is an [iPad 2](https://support.apple.com/kb/SP622)
- ///
- /// 
- case iPad2
- /// Device is an [iPad (3rd generation)](https://support.apple.com/kb/SP647)
- ///
- /// 
- case iPad3
- /// Device is an [iPad (4th generation)](https://support.apple.com/kb/SP662)
- ///
- /// 
- case iPad4
- /// Device is an [iPad Air](https://support.apple.com/kb/SP692)
- ///
- /// 
- case iPadAir
- /// Device is an [iPad Air 2](https://support.apple.com/kb/SP708)
- ///
- /// 
- case iPadAir2
- /// Device is an [iPad (5th generation)](https://support.apple.com/kb/SP751)
- ///
- /// 
- case iPad5
- /// Device is an [iPad (6th generation)](https://support.apple.com/kb/SP774)
- ///
- /// 
- case iPad6
- /// Device is an [iPad Air (3rd generation)](https://support.apple.com/kb/SP787)
- ///
- /// 
- case iPadAir3
- /// Device is an [iPad (7th generation)](https://support.apple.com/kb/SP807)
- ///
- /// 
- case iPad7
- /// Device is an [iPad (8th generation)](https://support.apple.com/kb/SP822)
- ///
- /// 
- case iPad8
- /// Device is an [iPad Air (4th generation)](https://support.apple.com/kb/SP828)
- ///
- /// 
- case iPadAir4
- /// Device is an [iPad Mini](https://support.apple.com/kb/SP661)
- ///
- /// 
- case iPadMini
- /// Device is an [iPad Mini 2](https://support.apple.com/kb/SP693)
- ///
- /// 
- case iPadMini2
- /// Device is an [iPad Mini 3](https://support.apple.com/kb/SP709)
- ///
- /// 
- case iPadMini3
- /// Device is an [iPad Mini 4](https://support.apple.com/kb/SP725)
- ///
- /// 
- case iPadMini4
- /// Device is an [iPad Mini (5th generation)](https://support.apple.com/kb/SP788)
- ///
- /// 
- case iPadMini5
- /// Device is an [iPad Pro 9.7-inch](https://support.apple.com/kb/SP739)
- ///
- /// 
- case iPadPro9Inch
- /// Device is an [iPad Pro 12-inch](https://support.apple.com/kb/SP723)
- ///
- /// 
- case iPadPro12Inch
- /// Device is an [iPad Pro 12-inch (2nd generation)](https://support.apple.com/kb/SP761)
- ///
- /// 
- case iPadPro12Inch2
- /// Device is an [iPad Pro 10.5-inch](https://support.apple.com/kb/SP762)
- ///
- /// 
- case iPadPro10Inch
- /// Device is an [iPad Pro 11-inch](https://support.apple.com/kb/SP784)
- ///
- /// 
- case iPadPro11Inch
- /// Device is an [iPad Pro 12.9-inch (3rd generation)](https://support.apple.com/kb/SP785)
- ///
- /// 
- case iPadPro12Inch3
- /// Device is an [iPad Pro 11-inch (2nd generation)](https://support.apple.com/kb/SP814)
- ///
- /// 
- case iPadPro11Inch2
- /// Device is an [iPad Pro 12.9-inch (4th generation)](https://support.apple.com/kb/SP815)
- ///
- /// 
- case iPadPro12Inch4
- /// Device is an [iPad Pro 11-inch (3rd generation)](https://support.apple.com/kb/TODO)
- ///
- /// 
- case iPadPro11Inch3
- /// Device is an [iPad Pro 12.9-inch (5th generation)](https://support.apple.com/kb/TODO)
- ///
- /// 
- case iPadPro12Inch5
- /// Device is a [HomePod](https://support.apple.com/kb/SP773)
- ///
- /// 
- case homePod
- #elseif os(tvOS)
- /// Device is an [Apple TV HD](https://support.apple.com/kb/SP724) (Previously Apple TV (4th generation))
- ///
- /// 
- case appleTVHD
- /// Device is an [Apple TV 4K](https://support.apple.com/kb/SP769)
- ///
- /// 
- case appleTV4K
- /// Device is an [Apple TV 4K (2nd generation)](https://support.apple.com/kb/TODO)
- ///
- /// 
- case appleTV4K2
- #elseif os(watchOS)
- /// Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)
- ///
- /// 
- case appleWatchSeries0_38mm
- /// Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)
- ///
- /// 
- case appleWatchSeries0_42mm
- /// Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)
- ///
- /// 
- case appleWatchSeries1_38mm
- /// Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)
- ///
- /// 
- case appleWatchSeries1_42mm
- /// Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)
- ///
- /// 
- case appleWatchSeries2_38mm
- /// Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)
- ///
- /// 
- case appleWatchSeries2_42mm
- /// Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)
- ///
- /// 
- case appleWatchSeries3_38mm
- /// Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)
- ///
- /// 
- case appleWatchSeries3_42mm
- /// Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)
- ///
- /// 
- case appleWatchSeries4_40mm
- /// Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)
- ///
- /// 
- case appleWatchSeries4_44mm
- /// Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)
- ///
- /// 
- case appleWatchSeries5_40mm
- /// Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)
- ///
- /// 
- case appleWatchSeries5_44mm
- /// Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)
- ///
- /// 
- case appleWatchSeries6_40mm
- /// Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)
- ///
- /// 
- case appleWatchSeries6_44mm
- /// Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)
- ///
- /// 
- case appleWatchSE_40mm
- /// Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)
- ///
- /// 
- case appleWatchSE_44mm
- #endif
- /// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)
- ///
- /// 
- indirect case simulator(Device)
- /// Device is not yet known (implemented)
- /// You can still use this enum as before but the description equals the identifier (you can get multiple identifiers for the same product class
- /// (e.g. "iPhone6,1" or "iPhone 6,2" do both mean "iPhone 5s"))
- case unknown(String)
- /// Returns a `Device` representing the current device this software runs on.
- public static var current: Device {
- return Device.mapToDevice(identifier: Device.identifier)
- }
- /// Gets the identifier from the system, such as "iPhone7,1".
- public static var identifier: String = {
- var systemInfo = utsname()
- uname(&systemInfo)
- let mirror = Mirror(reflecting: systemInfo.machine)
- let identifier = mirror.children.reduce("") { identifier, element in
- guard let value = element.value as? Int8, value != 0 else { return identifier }
- return identifier + String(UnicodeScalar(UInt8(value)))
- }
- return identifier
- }()
- /// Maps an identifier to a Device. If the identifier can not be mapped to an existing device, `UnknownDevice(identifier)` is returned.
- ///
- /// - parameter identifier: The device identifier, e.g. "iPhone7,1". Can be obtained from `Device.identifier`.
- ///
- /// - returns: An initialized `Device`.
- public static func mapToDevice(identifier: String) -> Device { // swiftlint:disable:this cyclomatic_complexity function_body_length
- #if os(iOS)
- switch identifier {
- case "iPod5,1": return iPodTouch5
- case "iPod7,1": return iPodTouch6
- case "iPod9,1": return iPodTouch7
- case "iPhone3,1", "iPhone3,2", "iPhone3,3": return iPhone4
- case "iPhone4,1": return iPhone4s
- case "iPhone5,1", "iPhone5,2": return iPhone5
- case "iPhone5,3", "iPhone5,4": return iPhone5c
- case "iPhone6,1", "iPhone6,2": return iPhone5s
- case "iPhone7,2": return iPhone6
- case "iPhone7,1": return iPhone6Plus
- case "iPhone8,1": return iPhone6s
- case "iPhone8,2": return iPhone6sPlus
- case "iPhone9,1", "iPhone9,3": return iPhone7
- case "iPhone9,2", "iPhone9,4": return iPhone7Plus
- case "iPhone8,4": return iPhoneSE
- case "iPhone10,1", "iPhone10,4": return iPhone8
- case "iPhone10,2", "iPhone10,5": return iPhone8Plus
- case "iPhone10,3", "iPhone10,6": return iPhoneX
- case "iPhone11,2": return iPhoneXS
- case "iPhone11,4", "iPhone11,6": return iPhoneXSMax
- case "iPhone11,8": return iPhoneXR
- case "iPhone12,1": return iPhone11
- case "iPhone12,3": return iPhone11Pro
- case "iPhone12,5": return iPhone11ProMax
- case "iPhone12,8": return iPhoneSE2
- case "iPhone13,2": return iPhone12
- case "iPhone13,1": return iPhone12Mini
- case "iPhone13,3": return iPhone12Pro
- case "iPhone13,4": return iPhone12ProMax
- 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
- case "iPad4,1", "iPad4,2", "iPad4,3": return iPadAir
- case "iPad5,3", "iPad5,4": return iPadAir2
- case "iPad6,11", "iPad6,12": return iPad5
- case "iPad7,5", "iPad7,6": return iPad6
- case "iPad11,3", "iPad11,4": return iPadAir3
- case "iPad7,11", "iPad7,12": return iPad7
- case "iPad11,6", "iPad11,7": return iPad8
- case "iPad13,1", "iPad13,2": return iPadAir4
- case "iPad2,5", "iPad2,6", "iPad2,7": return iPadMini
- case "iPad4,4", "iPad4,5", "iPad4,6": return iPadMini2
- case "iPad4,7", "iPad4,8", "iPad4,9": return iPadMini3
- case "iPad5,1", "iPad5,2": return iPadMini4
- case "iPad11,1", "iPad11,2": return iPadMini5
- case "iPad6,3", "iPad6,4": return iPadPro9Inch
- case "iPad6,7", "iPad6,8": return iPadPro12Inch
- case "iPad7,1", "iPad7,2": return iPadPro12Inch2
- case "iPad7,3", "iPad7,4": return iPadPro10Inch
- case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4": return iPadPro11Inch
- case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8": return iPadPro12Inch3
- case "iPad8,9", "iPad8,10": return iPadPro11Inch2
- case "iPad8,11", "iPad8,12": return iPadPro12Inch4
- case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7": return iPadPro11Inch3
- case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": return iPadPro12Inch5
- case "AudioAccessory1,1": return homePod
- case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))
- default: return unknown(identifier)
- }
- #elseif os(tvOS)
- switch identifier {
- case "AppleTV5,3": return appleTVHD
- case "AppleTV6,2": return appleTV4K
- case "AppleTV11,1": return appleTV4K2
- case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))
- default: return unknown(identifier)
- }
- #elseif os(watchOS)
- switch identifier {
- case "Watch1,1": return appleWatchSeries0_38mm
- case "Watch1,2": return appleWatchSeries0_42mm
- case "Watch2,6": return appleWatchSeries1_38mm
- case "Watch2,7": return appleWatchSeries1_42mm
- case "Watch2,3": return appleWatchSeries2_38mm
- case "Watch2,4": return appleWatchSeries2_42mm
- case "Watch3,1", "Watch3,3": return appleWatchSeries3_38mm
- case "Watch3,2", "Watch3,4": return appleWatchSeries3_42mm
- case "Watch4,1", "Watch4,3": return appleWatchSeries4_40mm
- case "Watch4,2", "Watch4,4": return appleWatchSeries4_44mm
- case "Watch5,1", "Watch5,3": return appleWatchSeries5_40mm
- case "Watch5,2", "Watch5,4": return appleWatchSeries5_44mm
- case "Watch6,1", "Watch6,3": return appleWatchSeries6_40mm
- case "Watch6,2", "Watch6,4": return appleWatchSeries6_44mm
- case "Watch5,9", "Watch5,11": return appleWatchSE_40mm
- case "Watch5,10", "Watch5,12": return appleWatchSE_44mm
- case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "watchOS"))
- default: return unknown(identifier)
- }
- #endif
- }
- /// Get the real device from a device.
- /// If the device is a an iPhone8Plus simulator this function returns .iPhone8Plus (the real device).
- /// If the parameter is a real device, this function returns just that passed parameter.
- ///
- /// - parameter device: A device.
- ///
- /// - returns: the underlying device If the `device` is a `simulator`,
- /// otherwise return the `device`.
- public static func realDevice(from device: Device) -> Device {
- if case let .simulator(model) = device {
- return model
- }
- return device
- }
- #if os(iOS) || os(watchOS)
- /// Returns diagonal screen length in inches
- public var diagonal: Double {
- #if os(iOS)
- switch self {
- case .iPodTouch5: return 4
- case .iPodTouch6: return 4
- case .iPodTouch7: return 4
- case .iPhone4: return 3.5
- case .iPhone4s: return 3.5
- case .iPhone5: return 4
- case .iPhone5c: return 4
- case .iPhone5s: return 4
- case .iPhone6: return 4.7
- case .iPhone6Plus: return 5.5
- case .iPhone6s: return 4.7
- case .iPhone6sPlus: return 5.5
- case .iPhone7: return 4.7
- case .iPhone7Plus: return 5.5
- case .iPhoneSE: return 4
- case .iPhone8: return 4.7
- case .iPhone8Plus: return 5.5
- case .iPhoneX: return 5.8
- case .iPhoneXS: return 5.8
- case .iPhoneXSMax: return 6.5
- case .iPhoneXR: return 6.1
- case .iPhone11: return 6.1
- case .iPhone11Pro: return 5.8
- case .iPhone11ProMax: return 6.5
- case .iPhoneSE2: return 4.7
- case .iPhone12: return 6.1
- case .iPhone12Mini: return 5.4
- case .iPhone12Pro: return 6.1
- case .iPhone12ProMax: return 6.7
- case .iPad2: return 9.7
- case .iPad3: return 9.7
- case .iPad4: return 9.7
- case .iPadAir: return 9.7
- case .iPadAir2: return 9.7
- case .iPad5: return 9.7
- case .iPad6: return 9.7
- case .iPadAir3: return 10.5
- case .iPad7: return 10.2
- case .iPad8: return 10.2
- case .iPadAir4: return 10.9
- case .iPadMini: return 7.9
- case .iPadMini2: return 7.9
- case .iPadMini3: return 7.9
- case .iPadMini4: return 7.9
- case .iPadMini5: return 7.9
- case .iPadPro9Inch: return 9.7
- case .iPadPro12Inch: return 12.9
- case .iPadPro12Inch2: return 12.9
- case .iPadPro10Inch: return 10.5
- case .iPadPro11Inch: return 11.0
- case .iPadPro12Inch3: return 12.9
- case .iPadPro11Inch2: return 11.0
- case .iPadPro12Inch4: return 12.9
- case .iPadPro11Inch3: return 11.0
- case .iPadPro12Inch5: return 12.9
- case .homePod: return -1
- case .simulator(let model): return model.diagonal
- case .unknown: return -1
- }
- #elseif os(watchOS)
- switch self {
- case .appleWatchSeries0_38mm: return 1.5
- case .appleWatchSeries0_42mm: return 1.6
- case .appleWatchSeries1_38mm: return 1.5
- case .appleWatchSeries1_42mm: return 1.6
- case .appleWatchSeries2_38mm: return 1.5
- case .appleWatchSeries2_42mm: return 1.6
- case .appleWatchSeries3_38mm: return 1.5
- case .appleWatchSeries3_42mm: return 1.6
- case .appleWatchSeries4_40mm: return 1.8
- case .appleWatchSeries4_44mm: return 2.0
- case .appleWatchSeries5_40mm: return 1.8
- case .appleWatchSeries5_44mm: return 2.0
- case .appleWatchSeries6_40mm: return 1.8
- case .appleWatchSeries6_44mm: return 2.0
- case .appleWatchSE_40mm: return 1.8
- case .appleWatchSE_44mm: return 2.0
- case .simulator(let model): return model.diagonal
- case .unknown: return -1
- }
- #endif
- }
- #endif
- /// Returns screen ratio as a tuple
- public var screenRatio: (width: Double, height: Double) {
- #if os(iOS)
- switch self {
- case .iPodTouch5: return (width: 9, height: 16)
- case .iPodTouch6: return (width: 9, height: 16)
- case .iPodTouch7: return (width: 9, height: 16)
- case .iPhone4: return (width: 2, height: 3)
- case .iPhone4s: return (width: 2, height: 3)
- case .iPhone5: return (width: 9, height: 16)
- case .iPhone5c: return (width: 9, height: 16)
- case .iPhone5s: return (width: 9, height: 16)
- case .iPhone6: return (width: 9, height: 16)
- case .iPhone6Plus: return (width: 9, height: 16)
- case .iPhone6s: return (width: 9, height: 16)
- case .iPhone6sPlus: return (width: 9, height: 16)
- case .iPhone7: return (width: 9, height: 16)
- case .iPhone7Plus: return (width: 9, height: 16)
- case .iPhoneSE: return (width: 9, height: 16)
- case .iPhone8: return (width: 9, height: 16)
- case .iPhone8Plus: return (width: 9, height: 16)
- case .iPhoneX: return (width: 9, height: 19.5)
- case .iPhoneXS: return (width: 9, height: 19.5)
- case .iPhoneXSMax: return (width: 9, height: 19.5)
- case .iPhoneXR: return (width: 9, height: 19.5)
- case .iPhone11: return (width: 9, height: 19.5)
- case .iPhone11Pro: return (width: 9, height: 19.5)
- case .iPhone11ProMax: return (width: 9, height: 19.5)
- case .iPhoneSE2: return (width: 9, height: 16)
- case .iPhone12: return (width: 9, height: 19.5)
- case .iPhone12Mini: return (width: 9, height: 19.5)
- case .iPhone12Pro: return (width: 9, height: 19.5)
- case .iPhone12ProMax: 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)
- case .iPadAir: return (width: 3, height: 4)
- case .iPadAir2: return (width: 3, height: 4)
- case .iPad5: return (width: 3, height: 4)
- case .iPad6: return (width: 3, height: 4)
- case .iPadAir3: return (width: 3, height: 4)
- case .iPad7: return (width: 3, height: 4)
- case .iPad8: return (width: 3, height: 4)
- case .iPadAir4: return (width: 41, height: 59)
- case .iPadMini: return (width: 3, height: 4)
- case .iPadMini2: return (width: 3, height: 4)
- case .iPadMini3: return (width: 3, height: 4)
- case .iPadMini4: return (width: 3, height: 4)
- case .iPadMini5: return (width: 3, height: 4)
- case .iPadPro9Inch: return (width: 3, height: 4)
- case .iPadPro12Inch: return (width: 3, height: 4)
- case .iPadPro12Inch2: return (width: 3, height: 4)
- case .iPadPro10Inch: return (width: 3, height: 4)
- case .iPadPro11Inch: return (width: 139, height: 199)
- case .iPadPro12Inch3: return (width: 512, height: 683)
- case .iPadPro11Inch2: return (width: 139, height: 199)
- case .iPadPro12Inch4: return (width: 512, height: 683)
- case .iPadPro11Inch3: return (width: 139, height: 199)
- case .iPadPro12Inch5: return (width: 512, height: 683)
- case .homePod: return (width: 4, height: 5)
- case .simulator(let model): return model.screenRatio
- case .unknown: return (width: -1, height: -1)
- }
- #elseif os(watchOS)
- switch self {
- case .appleWatchSeries0_38mm: return (width: 4, height: 5)
- case .appleWatchSeries0_42mm: return (width: 4, height: 5)
- case .appleWatchSeries1_38mm: return (width: 4, height: 5)
- case .appleWatchSeries1_42mm: return (width: 4, height: 5)
- case .appleWatchSeries2_38mm: return (width: 4, height: 5)
- case .appleWatchSeries2_42mm: return (width: 4, height: 5)
- case .appleWatchSeries3_38mm: return (width: 4, height: 5)
- case .appleWatchSeries3_42mm: return (width: 4, height: 5)
- case .appleWatchSeries4_40mm: return (width: 4, height: 5)
- case .appleWatchSeries4_44mm: return (width: 4, height: 5)
- case .appleWatchSeries5_40mm: return (width: 4, height: 5)
- case .appleWatchSeries5_44mm: return (width: 4, height: 5)
- case .appleWatchSeries6_40mm: return (width: 4, height: 5)
- case .appleWatchSeries6_44mm: return (width: 4, height: 5)
- case .appleWatchSE_40mm: return (width: 4, height: 5)
- case .appleWatchSE_44mm: return (width: 4, height: 5)
- case .simulator(let model): return model.screenRatio
- case .unknown: return (width: -1, height: -1)
- }
- #elseif os(tvOS)
- return (width: -1, height: -1)
- #endif
- }
- #if os(iOS)
- /// All iPods
- public static var allPods: [Device] {
- return [.iPodTouch5, .iPodTouch6, .iPodTouch7]
- }
- /// 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]
- }
- /// All iPads
- public static var allPads: [Device] {
- return [.iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// 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]
- }
- /// All Plus and Max-Sized Devices
- public static var allPlusSizedDevices: [Device] {
- return [.iPhone6Plus, .iPhone6sPlus, .iPhone7Plus, .iPhone8Plus, .iPhoneXSMax, .iPhone11ProMax, .iPhone12ProMax]
- }
- /// All Pro Devices
- public static var allProDevices: [Device] {
- return [.iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// All mini Devices
- public static var allMiniDevices: [Device] {
- return [.iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5]
- }
- /// All simulator iPods
- public static var allSimulatorPods: [Device] {
- return allPods.map(Device.simulator)
- }
- /// All simulator iPhones
- public static var allSimulatorPhones: [Device] {
- return allPhones.map(Device.simulator)
- }
- /// All simulator iPads
- public static var allSimulatorPads: [Device] {
- return allPads.map(Device.simulator)
- }
- /// All simulator iPad mini
- public static var allSimulatorMiniDevices: [Device] {
- return allMiniDevices.map(Device.simulator)
- }
- /// All simulator X series Devices
- @available(*, deprecated, renamed: "allSimulatorDevicesWithSensorHousing")
- public static var allSimulatorXSeriesDevices: [Device] {
- return allDevicesWithSensorHousing.map(Device.simulator)
- }
- /// All simulator Plus and Max-Sized Devices
- public static var allSimulatorPlusSizedDevices: [Device] {
- return allPlusSizedDevices.map(Device.simulator)
- }
- /// All simulator Pro Devices
- public static var allSimulatorProDevices: [Device] {
- return allProDevices.map(Device.simulator)
- }
- /// Returns whether the device is an iPod (real or simulator)
- public var isPod: Bool {
- return isOneOf(Device.allPods) || isOneOf(Device.allSimulatorPods)
- }
- /// Returns whether the device is an iPhone (real or simulator)
- public var isPhone: Bool {
- return (isOneOf(Device.allPhones)
- || isOneOf(Device.allSimulatorPhones)
- || (UIDevice.current.userInterfaceIdiom == .phone && isCurrent)) && !isPod
- }
- /// Returns whether the device is an iPad (real or simulator)
- public var isPad: Bool {
- return isOneOf(Device.allPads)
- || isOneOf(Device.allSimulatorPads)
- || (UIDevice.current.userInterfaceIdiom == .pad && isCurrent)
- }
- /// Returns whether the device is any of the simulator
- /// Useful when there is a need to check and skip running a portion of code (location request or others)
- public var isSimulator: Bool {
- return isOneOf(Device.allSimulators)
- }
- /// If this device is a simulator return the underlying device,
- /// otherwise return `self`.
- public var realDevice: Device {
- return Device.realDevice(from: self)
- }
- public var isZoomed: Bool? {
- guard isCurrent else { return nil }
- if Int(UIScreen.main.scale.rounded()) == 3 {
- // Plus-sized
- return UIScreen.main.nativeScale > 2.7 && UIScreen.main.nativeScale < 3
- } else {
- return UIScreen.main.nativeScale > UIScreen.main.scale
- }
- }
- /// All Touch ID Capable Devices
- public static var allTouchIDCapableDevices: [Device] {
- return [.iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneSE2, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini3, .iPadMini4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch]
- }
- /// All Face ID Capable Devices
- public static var allFaceIDCapableDevices: [Device] {
- return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// 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, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini3, .iPadMini4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// Returns whether or not the device has Touch ID
- public var isTouchIDCapable: Bool {
- return isOneOf(Device.allTouchIDCapableDevices) || isOneOf(Device.allTouchIDCapableDevices.map(Device.simulator))
- }
- /// Returns whether or not the device has Face ID
- public var isFaceIDCapable: Bool {
- return isOneOf(Device.allFaceIDCapableDevices) || isOneOf(Device.allFaceIDCapableDevices.map(Device.simulator))
- }
- /// Returns whether or not the device has any biometric sensor (i.e. Touch ID or Face ID)
- public var hasBiometricSensor: Bool {
- return isTouchIDCapable || isFaceIDCapable
- }
- /// All devices that feature a sensor housing in the screen
- public static var allDevicesWithSensorHousing: [Device] {
- return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax]
- }
- /// All simulator devices that feature a sensor housing in the screen
- public static var allSimulatorDevicesWithSensorHousing: [Device] {
- return allDevicesWithSensorHousing.map(Device.simulator)
- }
- /// Returns whether or not the device has a sensor housing
- public var hasSensorHousing: Bool {
- return isOneOf(Device.allDevicesWithSensorHousing) || isOneOf(Device.allDevicesWithSensorHousing.map(Device.simulator))
- }
- /// All devices that feature a screen with rounded corners.
- public static var allDevicesWithRoundedDisplayCorners: [Device] {
- return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadAir4, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// Returns whether or not the device has a screen with rounded corners.
- public var hasRoundedDisplayCorners: Bool {
- return isOneOf(Device.allDevicesWithRoundedDisplayCorners) || isOneOf(Device.allDevicesWithRoundedDisplayCorners.map(Device.simulator))
- }
- /// All devices that have 3D Touch support.
- public static var allDevicesWith3dTouchSupport: [Device] {
- return [.iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax]
- }
- /// Returns whether or not the device has 3D Touch support.
- public var has3dTouchSupport: Bool {
- return isOneOf(Device.allDevicesWith3dTouchSupport) || isOneOf(Device.allDevicesWith3dTouchSupport.map(Device.simulator))
- }
- /// All devices that support wireless charging.
- public static var allDevicesWithWirelessChargingSupport: [Device] {
- return [.iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax]
- }
- /// Returns whether or not the device supports wireless charging.
- public var supportsWirelessCharging: Bool {
- return isOneOf(Device.allDevicesWithWirelessChargingSupport) || isOneOf(Device.allDevicesWithWirelessChargingSupport.map(Device.simulator))
- }
- /// All devices that have a LiDAR sensor.
- public static var allDevicesWithALidarSensor: [Device] {
- return [.iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// Returns whether or not the device has a LiDAR sensor.
- public var hasLidarSensor: Bool {
- return isOneOf(Device.allDevicesWithALidarSensor) || isOneOf(Device.allDevicesWithALidarSensor.map(Device.simulator))
- }
- #elseif os(tvOS)
- /// All TVs
- public static var allTVs: [Device] {
- return [.appleTVHD, .appleTV4K, .appleTV4K2]
- }
- /// All simulator TVs
- public static var allSimulatorTVs: [Device] {
- return allTVs.map(Device.simulator)
- }
- #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]
- }
- /// All simulator Watches
- public static var allSimulatorWatches: [Device] {
- return allWatches.map(Device.simulator)
- }
- /// All watches that have Force Touch support.
- public static var allWatchesWithForceTouchSupport: [Device] {
- return [.appleWatchSeries0_38mm, .appleWatchSeries0_42mm, .appleWatchSeries1_38mm, .appleWatchSeries1_42mm, .appleWatchSeries2_38mm, .appleWatchSeries2_42mm, .appleWatchSeries3_38mm, .appleWatchSeries3_42mm, .appleWatchSeries4_40mm, .appleWatchSeries4_44mm, .appleWatchSeries5_40mm, .appleWatchSeries5_44mm]
- }
- /// Returns whether or not the device has Force Touch support.
- public var hasForceTouchSupport: Bool {
- return isOneOf(Device.allWatchesWithForceTouchSupport) || isOneOf(Device.allWatchesWithForceTouchSupport.map(Device.simulator))
- }
- #endif
- /// All real devices (i.e. all devices except for all simulators)
- public static var allRealDevices: [Device] {
- #if os(iOS)
- return allPods + allPhones + allPads
- #elseif os(tvOS)
- return allTVs
- #elseif os(watchOS)
- return allWatches
- #endif
- }
- /// All simulators
- public static var allSimulators: [Device] {
- return allRealDevices.map(Device.simulator)
- }
- /**
- This method saves you in many cases from the need of updating your code with every new device.
- Most uses for an enum like this are the following:
- ```
- switch Device.current {
- case .iPodTouch5, .iPodTouch6: callMethodOnIPods()
- case .iPhone4, iPhone4s, .iPhone5, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX: callMethodOnIPhones()
- case .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadPro: callMethodOnIPads()
- default: break
- }
- ```
- This code can now be replaced with
- ```
- let device = Device.current
- if device.isOneOf(Device.allPods) {
- callMethodOnIPods()
- } else if device.isOneOf(Device.allPhones) {
- callMethodOnIPhones()
- } else if device.isOneOf(Device.allPads) {
- callMethodOnIPads()
- }
- ```
- - parameter devices: An array of devices.
- - returns: Returns whether the current device is one of the passed in ones.
- */
- public func isOneOf(_ devices: [Device]) -> Bool {
- return devices.contains(self)
- }
- // MARK: Current Device
- /// Whether or not the current device is the current device.
- private var isCurrent: Bool {
- return self == Device.current
- }
- /// The name identifying the device (e.g. "Dennis' iPhone").
- public var name: String? {
- guard isCurrent else { return nil }
- #if os(watchOS)
- return WKInterfaceDevice.current().name
- #else
- return UIDevice.current.name
- #endif
- }
- /// The name of the operating system running on the device represented by the receiver (e.g. "iOS" or "tvOS").
- public var systemName: String? {
- guard isCurrent else { return nil }
- #if os(watchOS)
- return WKInterfaceDevice.current().systemName
- #else
- return UIDevice.current.systemName
- #endif
- }
- /// The current version of the operating system (e.g. 8.4 or 9.2).
- public var systemVersion: String? {
- guard isCurrent else { return nil }
- #if os(watchOS)
- return WKInterfaceDevice.current().systemVersion
- #else
- return UIDevice.current.systemVersion
- #endif
- }
- /// The model of the device (e.g. "iPhone" or "iPod Touch").
- public var model: String? {
- guard isCurrent else { return nil }
- #if os(watchOS)
- return WKInterfaceDevice.current().model
- #else
- return UIDevice.current.model
- #endif
- }
- /// The model of the device as a localized string.
- public var localizedModel: String? {
- guard isCurrent else { return nil }
- #if os(watchOS)
- return WKInterfaceDevice.current().localizedModel
- #else
- return UIDevice.current.localizedModel
- #endif
- }
- /// PPI (Pixels per Inch) on the current device's screen (if applicable). When the device is not applicable this property returns nil.
- public var ppi: Int? {
- #if os(iOS)
- switch self {
- case .iPodTouch5: return 326
- case .iPodTouch6: return 326
- case .iPodTouch7: return 326
- case .iPhone4: return 326
- case .iPhone4s: return 326
- case .iPhone5: return 326
- case .iPhone5c: return 326
- case .iPhone5s: return 326
- case .iPhone6: return 326
- case .iPhone6Plus: return 401
- case .iPhone6s: return 326
- case .iPhone6sPlus: return 401
- case .iPhone7: return 326
- case .iPhone7Plus: return 401
- case .iPhoneSE: return 326
- case .iPhone8: return 326
- case .iPhone8Plus: return 401
- case .iPhoneX: return 458
- case .iPhoneXS: return 458
- case .iPhoneXSMax: return 458
- case .iPhoneXR: return 326
- case .iPhone11: return 326
- case .iPhone11Pro: return 458
- case .iPhone11ProMax: return 458
- case .iPhoneSE2: return 326
- case .iPhone12: return 460
- case .iPhone12Mini: return 476
- case .iPhone12Pro: return 460
- case .iPhone12ProMax: return 458
- case .iPad2: return 132
- case .iPad3: return 264
- case .iPad4: return 264
- case .iPadAir: return 264
- case .iPadAir2: return 264
- case .iPad5: return 264
- case .iPad6: return 264
- case .iPadAir3: return 264
- case .iPad7: return 264
- case .iPad8: return 264
- case .iPadAir4: return 264
- case .iPadMini: return 163
- case .iPadMini2: return 326
- case .iPadMini3: return 326
- case .iPadMini4: return 326
- case .iPadMini5: return 326
- case .iPadPro9Inch: return 264
- case .iPadPro12Inch: return 264
- case .iPadPro12Inch2: return 264
- case .iPadPro10Inch: return 264
- case .iPadPro11Inch: return 264
- case .iPadPro12Inch3: return 264
- case .iPadPro11Inch2: return 264
- case .iPadPro12Inch4: return 264
- case .iPadPro11Inch3: return 264
- case .iPadPro12Inch5: return 264
- case .homePod: return -1
- case .simulator(let model): return model.ppi
- case .unknown: return nil
- }
- #elseif os(watchOS)
- switch self {
- case .appleWatchSeries0_38mm: return 290
- case .appleWatchSeries0_42mm: return 303
- case .appleWatchSeries1_38mm: return 290
- case .appleWatchSeries1_42mm: return 303
- case .appleWatchSeries2_38mm: return 290
- case .appleWatchSeries2_42mm: return 303
- case .appleWatchSeries3_38mm: return 290
- case .appleWatchSeries3_42mm: return 303
- case .appleWatchSeries4_40mm: return 326
- case .appleWatchSeries4_44mm: return 326
- case .appleWatchSeries5_40mm: return 326
- case .appleWatchSeries5_44mm: return 326
- case .appleWatchSeries6_40mm: return 326
- case .appleWatchSeries6_44mm: return 326
- case .appleWatchSE_40mm: return 326
- case .appleWatchSE_44mm: return 326
- case .simulator(let model): return model.ppi
- case .unknown: return nil
- }
- #elseif os(tvOS)
- return nil
- #endif
- }
- /// True when a Guided Access session is currently active; otherwise, false.
- public var isGuidedAccessSessionActive: Bool {
- #if os(iOS)
- #if swift(>=4.2)
- return UIAccessibility.isGuidedAccessEnabled
- #else
- return UIAccessibilityIsGuidedAccessEnabled()
- #endif
- #else
- return false
- #endif
- }
- /// The brightness level of the screen.
- public var screenBrightness: Int {
- #if os(iOS)
- return Int(UIScreen.main.brightness * 100)
- #else
- return 100
- #endif
- }
- }
- // MARK: CustomStringConvertible
- extension Device: CustomStringConvertible {
- /// A textual representation of the device.
- public var description: String {
- #if os(iOS)
- switch self {
- case .iPodTouch5: return "iPod touch (5th generation)"
- case .iPodTouch6: return "iPod touch (6th generation)"
- case .iPodTouch7: return "iPod touch (7th generation)"
- case .iPhone4: return "iPhone 4"
- case .iPhone4s: return "iPhone 4s"
- case .iPhone5: return "iPhone 5"
- case .iPhone5c: return "iPhone 5c"
- case .iPhone5s: return "iPhone 5s"
- case .iPhone6: return "iPhone 6"
- case .iPhone6Plus: return "iPhone 6 Plus"
- case .iPhone6s: return "iPhone 6s"
- case .iPhone6sPlus: return "iPhone 6s Plus"
- case .iPhone7: return "iPhone 7"
- case .iPhone7Plus: return "iPhone 7 Plus"
- case .iPhoneSE: return "iPhone SE"
- case .iPhone8: return "iPhone 8"
- case .iPhone8Plus: return "iPhone 8 Plus"
- case .iPhoneX: return "iPhone X"
- case .iPhoneXS: return "iPhone Xs"
- case .iPhoneXSMax: return "iPhone Xs Max"
- case .iPhoneXR: return "iPhone Xʀ"
- case .iPhone11: return "iPhone 11"
- case .iPhone11Pro: return "iPhone 11 Pro"
- case .iPhone11ProMax: return "iPhone 11 Pro Max"
- case .iPhoneSE2: return "iPhone SE (2nd generation)"
- case .iPhone12: return "iPhone 12"
- case .iPhone12Mini: return "iPhone 12 mini"
- case .iPhone12Pro: return "iPhone 12 Pro"
- case .iPhone12ProMax: return "iPhone 12 Pro Max"
- case .iPad2: return "iPad 2"
- case .iPad3: return "iPad (3rd generation)"
- case .iPad4: return "iPad (4th generation)"
- case .iPadAir: return "iPad Air"
- case .iPadAir2: return "iPad Air 2"
- case .iPad5: return "iPad (5th generation)"
- case .iPad6: return "iPad (6th generation)"
- case .iPadAir3: return "iPad Air (3rd generation)"
- case .iPad7: return "iPad (7th generation)"
- case .iPad8: return "iPad (8th generation)"
- case .iPadAir4: return "iPad Air (4th generation)"
- case .iPadMini: return "iPad Mini"
- case .iPadMini2: return "iPad Mini 2"
- case .iPadMini3: return "iPad Mini 3"
- case .iPadMini4: return "iPad Mini 4"
- case .iPadMini5: return "iPad Mini (5th generation)"
- case .iPadPro9Inch: return "iPad Pro (9.7-inch)"
- case .iPadPro12Inch: return "iPad Pro (12.9-inch)"
- case .iPadPro12Inch2: return "iPad Pro (12.9-inch) (2nd generation)"
- case .iPadPro10Inch: return "iPad Pro (10.5-inch)"
- case .iPadPro11Inch: return "iPad Pro (11-inch)"
- case .iPadPro12Inch3: return "iPad Pro (12.9-inch) (3rd generation)"
- case .iPadPro11Inch2: return "iPad Pro (11-inch) (2nd generation)"
- case .iPadPro12Inch4: return "iPad Pro (12.9-inch) (4th generation)"
- case .iPadPro11Inch3: return "iPad Pro (11-inch) (3rd generation)"
- case .iPadPro12Inch5: return "iPad Pro (12.9-inch) (5th generation)"
- case .homePod: return "HomePod"
- case .simulator(let model): return "Simulator (\(model.description))"
- case .unknown(let identifier): return identifier
- }
- #elseif os(watchOS)
- switch self {
- case .appleWatchSeries0_38mm: return "Apple Watch (1st generation) 38mm"
- case .appleWatchSeries0_42mm: return "Apple Watch (1st generation) 42mm"
- case .appleWatchSeries1_38mm: return "Apple Watch Series 1 38mm"
- case .appleWatchSeries1_42mm: return "Apple Watch Series 1 42mm"
- case .appleWatchSeries2_38mm: return "Apple Watch Series 2 38mm"
- case .appleWatchSeries2_42mm: return "Apple Watch Series 2 42mm"
- case .appleWatchSeries3_38mm: return "Apple Watch Series 3 38mm"
- case .appleWatchSeries3_42mm: return "Apple Watch Series 3 42mm"
- case .appleWatchSeries4_40mm: return "Apple Watch Series 4 40mm"
- case .appleWatchSeries4_44mm: return "Apple Watch Series 4 44mm"
- case .appleWatchSeries5_40mm: return "Apple Watch Series 5 40mm"
- case .appleWatchSeries5_44mm: return "Apple Watch Series 5 44mm"
- case .appleWatchSeries6_40mm: return "Apple Watch Series 6 40mm"
- case .appleWatchSeries6_44mm: return "Apple Watch Series 6 44mm"
- case .appleWatchSE_40mm: return "Apple Watch SE 40mm"
- case .appleWatchSE_44mm: return "Apple Watch SE 44mm"
- case .simulator(let model): return "Simulator (\(model.description))"
- case .unknown(let identifier): return identifier
- }
- #elseif os(tvOS)
- switch self {
- case .appleTVHD: return "Apple TV HD"
- case .appleTV4K: return "Apple TV 4K"
- case .appleTV4K2: return "Apple TV 4K (2nd generation)"
- case .simulator(let model): return "Simulator (\(model.description))"
- case .unknown(let identifier): return identifier
- }
- #endif
- }
- /// A safe version of `description`.
- /// Example:
- /// Device.iPhoneXR.description: iPhone Xʀ
- /// Device.iPhoneXR.safeDescription: iPhone XR
- public var safeDescription: String {
- #if os(iOS)
- switch self {
- case .iPodTouch5: return "iPod touch (5th generation)"
- case .iPodTouch6: return "iPod touch (6th generation)"
- case .iPodTouch7: return "iPod touch (7th generation)"
- case .iPhone4: return "iPhone 4"
- case .iPhone4s: return "iPhone 4s"
- case .iPhone5: return "iPhone 5"
- case .iPhone5c: return "iPhone 5c"
- case .iPhone5s: return "iPhone 5s"
- case .iPhone6: return "iPhone 6"
- case .iPhone6Plus: return "iPhone 6 Plus"
- case .iPhone6s: return "iPhone 6s"
- case .iPhone6sPlus: return "iPhone 6s Plus"
- case .iPhone7: return "iPhone 7"
- case .iPhone7Plus: return "iPhone 7 Plus"
- case .iPhoneSE: return "iPhone SE"
- case .iPhone8: return "iPhone 8"
- case .iPhone8Plus: return "iPhone 8 Plus"
- case .iPhoneX: return "iPhone X"
- case .iPhoneXS: return "iPhone XS"
- case .iPhoneXSMax: return "iPhone XS Max"
- case .iPhoneXR: return "iPhone XR"
- case .iPhone11: return "iPhone 11"
- case .iPhone11Pro: return "iPhone 11 Pro"
- case .iPhone11ProMax: return "iPhone 11 Pro Max"
- case .iPhoneSE2: return "iPhone SE (2nd generation)"
- case .iPhone12: return "iPhone 12"
- case .iPhone12Mini: return "iPhone 12 mini"
- case .iPhone12Pro: return "iPhone 12 Pro"
- case .iPhone12ProMax: return "iPhone 12 Pro Max"
- case .iPad2: return "iPad 2"
- case .iPad3: return "iPad (3rd generation)"
- case .iPad4: return "iPad (4th generation)"
- case .iPadAir: return "iPad Air"
- case .iPadAir2: return "iPad Air 2"
- case .iPad5: return "iPad (5th generation)"
- case .iPad6: return "iPad (6th generation)"
- case .iPadAir3: return "iPad Air (3rd generation)"
- case .iPad7: return "iPad (7th generation)"
- case .iPad8: return "iPad (8th generation)"
- case .iPadAir4: return "iPad Air (4th generation)"
- case .iPadMini: return "iPad Mini"
- case .iPadMini2: return "iPad Mini 2"
- case .iPadMini3: return "iPad Mini 3"
- case .iPadMini4: return "iPad Mini 4"
- case .iPadMini5: return "iPad Mini (5th generation)"
- case .iPadPro9Inch: return "iPad Pro (9.7-inch)"
- case .iPadPro12Inch: return "iPad Pro (12.9-inch)"
- case .iPadPro12Inch2: return "iPad Pro (12.9-inch) (2nd generation)"
- case .iPadPro10Inch: return "iPad Pro (10.5-inch)"
- case .iPadPro11Inch: return "iPad Pro (11-inch)"
- case .iPadPro12Inch3: return "iPad Pro (12.9-inch) (3rd generation)"
- case .iPadPro11Inch2: return "iPad Pro (11-inch) (2nd generation)"
- case .iPadPro12Inch4: return "iPad Pro (12.9-inch) (4th generation)"
- case .iPadPro11Inch3: return "iPad Pro (11-inch) (3rd generation)"
- case .iPadPro12Inch5: return "iPad Pro (12.9-inch) (5th generation)"
- case .homePod: return "HomePod"
- case .simulator(let model): return "Simulator (\(model.safeDescription))"
- case .unknown(let identifier): return identifier
- }
- #elseif os(watchOS)
- switch self {
- case .appleWatchSeries0_38mm: return "Apple Watch (1st generation) 38mm"
- case .appleWatchSeries0_42mm: return "Apple Watch (1st generation) 42mm"
- case .appleWatchSeries1_38mm: return "Apple Watch Series 1 38mm"
- case .appleWatchSeries1_42mm: return "Apple Watch Series 1 42mm"
- case .appleWatchSeries2_38mm: return "Apple Watch Series 2 38mm"
- case .appleWatchSeries2_42mm: return "Apple Watch Series 2 42mm"
- case .appleWatchSeries3_38mm: return "Apple Watch Series 3 38mm"
- case .appleWatchSeries3_42mm: return "Apple Watch Series 3 42mm"
- case .appleWatchSeries4_40mm: return "Apple Watch Series 4 40mm"
- case .appleWatchSeries4_44mm: return "Apple Watch Series 4 44mm"
- case .appleWatchSeries5_40mm: return "Apple Watch Series 5 40mm"
- case .appleWatchSeries5_44mm: return "Apple Watch Series 5 44mm"
- case .appleWatchSeries6_40mm: return "Apple Watch Series 6 40mm"
- case .appleWatchSeries6_44mm: return "Apple Watch Series 6 44mm"
- case .appleWatchSE_40mm: return "Apple Watch SE 40mm"
- case .appleWatchSE_44mm: return "Apple Watch SE 44mm"
- case .simulator(let model): return "Simulator (\(model.safeDescription))"
- case .unknown(let identifier): return identifier
- }
- #elseif os(tvOS)
- switch self {
- case .appleTVHD: return "Apple TV HD"
- case .appleTV4K: return "Apple TV 4K"
- case .appleTV4K2: return "Apple TV 4K (2nd generation)"
- case .simulator(let model): return "Simulator (\(model.safeDescription))"
- case .unknown(let identifier): return identifier
- }
- #endif
- }
- }
- // MARK: Equatable
- extension Device: Equatable {
- /// Compares two devices
- ///
- /// - parameter lhs: A device.
- /// - parameter rhs: Another device.
- ///
- /// - returns: `true` iff the underlying identifier is the same.
- public static func == (lhs: Device, rhs: Device) -> Bool {
- return lhs.description == rhs.description
- }
- }
- // MARK: Battery
- #if os(iOS) || os(watchOS)
- @available(iOS 8.0, watchOS 4.0, *)
- extension Device {
- /**
- This enum describes the state of the battery.
- - Full: The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
- - Charging: The device is plugged into power and the battery is less than 100% charged.
- - Unplugged: The device is not plugged into power; the battery is discharging.
- */
- public enum BatteryState: CustomStringConvertible, Equatable {
- /// The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
- case full
- /// The device is plugged into power and the battery is less than 100% charged.
- /// The associated value is in percent (0-100).
- case charging(Int)
- /// The device is not plugged into power; the battery is discharging.
- /// The associated value is in percent (0-100).
- case unplugged(Int)
- #if os(iOS)
- fileprivate init() {
- let wasBatteryMonitoringEnabled = UIDevice.current.isBatteryMonitoringEnabled
- UIDevice.current.isBatteryMonitoringEnabled = true
- let batteryLevel = Int(round(UIDevice.current.batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number
- // but maybe that changes in the future.
- switch UIDevice.current.batteryState {
- case .charging: self = .charging(batteryLevel)
- case .full: self = .full
- case .unplugged: self = .unplugged(batteryLevel)
- case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
- @unknown default:
- self = .full // To cover any future additions for which DeviceKit might not have updated yet.
- }
- UIDevice.current.isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
- }
- #elseif os(watchOS)
- fileprivate init() {
- let wasBatteryMonitoringEnabled = WKInterfaceDevice.current().isBatteryMonitoringEnabled
- WKInterfaceDevice.current().isBatteryMonitoringEnabled = true
- let batteryLevel = Int(round(WKInterfaceDevice.current().batteryLevel * 100)) // round() is actually not needed anymore since -[batteryLevel] seems to always return a two-digit precision number
- // but maybe that changes in the future.
- switch WKInterfaceDevice.current().batteryState {
- case .charging: self = .charging(batteryLevel)
- case .full: self = .full
- case .unplugged: self = .unplugged(batteryLevel)
- case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
- @unknown default:
- self = .full // To cover any future additions for which DeviceKit might not have updated yet.
- }
- WKInterfaceDevice.current().isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
- }
- #endif
- /// The user enabled Low Power mode
- public var lowPowerMode: Bool {
- return ProcessInfo.processInfo.isLowPowerModeEnabled
- }
- /// Provides a textual representation of the battery state.
- /// Examples:
- /// ```
- /// Battery level: 90%, device is plugged in.
- /// Battery level: 100 % (Full), device is plugged in.
- /// Battery level: \(batteryLevel)%, device is unplugged.
- /// ```
- public var description: String {
- switch self {
- case .charging(let batteryLevel): return "Battery level: \(batteryLevel)%, device is plugged in."
- case .full: return "Battery level: 100 % (Full), device is plugged in."
- case .unplugged(let batteryLevel): return "Battery level: \(batteryLevel)%, device is unplugged."
- }
- }
- }
- /// The state of the battery
- public var batteryState: BatteryState? {
- guard isCurrent else { return nil }
- return BatteryState()
- }
- /// Battery level ranges from 0 (fully discharged) to 100 (100% charged).
- public var batteryLevel: Int? {
- guard isCurrent else { return nil }
- switch BatteryState() {
- case .charging(let value): return value
- case .full: return 100
- case .unplugged(let value): return value
- }
- }
- }
- #endif
- // MARK: Device.Batterystate: Comparable
- #if os(iOS) || os(watchOS)
- @available(iOS 8.0, watchOS 4.0, *)
- extension Device.BatteryState: Comparable {
- /// Tells if two battery states are equal.
- ///
- /// - parameter lhs: A battery state.
- /// - parameter rhs: Another battery state.
- ///
- /// - returns: `true` iff they are equal, otherwise `false`
- public static func == (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
- return lhs.description == rhs.description
- }
- /// Compares two battery states.
- ///
- /// - parameter lhs: A battery state.
- /// - parameter rhs: Another battery state.
- ///
- /// - returns: `true` if rhs is `.Full`, `false` when lhs is `.Full` otherwise their battery level is compared.
- public static func < (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
- switch (lhs, rhs) {
- case (.full, _): return false // return false (even if both are `.Full` -> they are equal)
- case (_, .full): return true // lhs is *not* `.Full`, rhs is
- case let (.charging(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
- case let (.charging(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
- case let (.unplugged(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
- case let (.unplugged(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
- default: return false // compiler won't compile without it, though it cannot happen
- }
- }
- }
- #endif
- #if os(iOS)
- extension Device {
- // MARK: Orientation
- /**
- This enum describes the state of the orientation.
- - Landscape: The device is in Landscape Orientation
- - Portrait: The device is in Portrait Orientation
- */
- public enum Orientation {
- case landscape
- case portrait
- }
- public var orientation: Orientation {
- if UIDevice.current.orientation.isLandscape {
- return .landscape
- } else {
- return .portrait
- }
- }
- }
- #endif
- #if os(iOS)
- // MARK: DiskSpace
- extension Device {
- /// Return the root url
- ///
- /// - returns: the NSHomeDirectory() url
- private static let rootURL = URL(fileURLWithPath: NSHomeDirectory())
- /// The volume’s total capacity in bytes.
- public static var volumeTotalCapacity: Int? {
- return (try? Device.rootURL.resourceValues(forKeys: [.volumeTotalCapacityKey]))?.volumeTotalCapacity
- }
- /// The volume’s available capacity in bytes.
- public static var volumeAvailableCapacity: Int? {
- return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityKey]))?.volumeAvailableCapacity
- }
- /// The volume’s available capacity in bytes for storing important resources.
- @available(iOS 11.0, *)
- public static var volumeAvailableCapacityForImportantUsage: Int64? {
- return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]))?.volumeAvailableCapacityForImportantUsage
- }
- /// The volume’s available capacity in bytes for storing nonessential resources.
- @available(iOS 11.0, *)
- public static var volumeAvailableCapacityForOpportunisticUsage: Int64? { //swiftlint:disable:this identifier_name
- return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForOpportunisticUsageKey]))?.volumeAvailableCapacityForOpportunisticUsage
- }
- /// All volumes capacity information in bytes.
- @available(iOS 11.0, *)
- public static var volumes: [URLResourceKey: Int64]? {
- do {
- let values = try rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey,
- .volumeAvailableCapacityKey,
- .volumeAvailableCapacityForOpportunisticUsageKey,
- .volumeTotalCapacityKey
- ])
- return values.allValues.mapValues {
- if let int = $0 as? Int64 {
- return int
- }
- if let int = $0 as? Int {
- return Int64(int)
- }
- return 0
- }
- } catch {
- return nil
- }
- }
- }
- #endif
- #if os(iOS)
- // MARK: Apple Pencil
- extension Device {
- /**
- This option set describes the current Apple Pencils
- - firstGeneration: 1st Generation Apple Pencil
- - secondGeneration: 2nd Generation Apple Pencil
- */
- public struct ApplePencilSupport: OptionSet {
- public var rawValue: UInt
- public init(rawValue: UInt) {
- self.rawValue = rawValue
- }
- public static let firstGeneration = ApplePencilSupport(rawValue: 0x01)
- public static let secondGeneration = ApplePencilSupport(rawValue: 0x02)
- }
- /// All Apple Pencil Capable Devices
- public static var allApplePencilCapableDevices: [Device] {
- return [.iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// Returns supported version of the Apple Pencil
- public var applePencilSupport: ApplePencilSupport {
- switch self {
- case .iPad6: return .firstGeneration
- case .iPadAir3: return .firstGeneration
- case .iPad7: return .firstGeneration
- case .iPad8: return .firstGeneration
- case .iPadMini5: return .firstGeneration
- case .iPadPro9Inch: return .firstGeneration
- case .iPadPro12Inch: return .firstGeneration
- case .iPadPro12Inch2: return .firstGeneration
- case .iPadPro10Inch: return .firstGeneration
- case .iPadAir4: return .secondGeneration
- case .iPadPro11Inch: return .secondGeneration
- case .iPadPro12Inch3: return .secondGeneration
- case .iPadPro11Inch2: return .secondGeneration
- case .iPadPro12Inch4: return .secondGeneration
- case .iPadPro11Inch3: return .secondGeneration
- case .iPadPro12Inch5: return .secondGeneration
- case .simulator(let model): return model.applePencilSupport
- default: return []
- }
- }
- }
- #endif
- #if os(iOS)
- // MARK: Cameras
- extension Device {
- public enum CameraType {
- @available(*, deprecated, renamed: "wide")
- case normal
- case wide
- case telephoto
- case ultraWide
- }
- /// Returns an array of the types of cameras the device has
- public var cameras: [CameraType] {
- switch self {
- case .iPodTouch5: return [.wide]
- case .iPodTouch6: return [.wide]
- case .iPodTouch7: return [.wide]
- case .iPhone4: return [.wide]
- case .iPhone4s: return [.wide]
- case .iPhone5: return [.wide]
- case .iPhone5c: return [.wide]
- case .iPhone5s: return [.wide]
- case .iPhone6: return [.wide]
- case .iPhone6Plus: return [.wide]
- case .iPhone6s: return [.wide]
- case .iPhone6sPlus: return [.wide]
- case .iPhone7: return [.wide]
- case .iPhoneSE: return [.wide]
- case .iPhone8: return [.wide]
- case .iPhoneXR: return [.wide]
- case .iPhoneSE2: return [.wide]
- case .iPad2: return [.wide]
- case .iPad3: return [.wide]
- case .iPad4: return [.wide]
- case .iPadAir: return [.wide]
- case .iPadAir2: return [.wide]
- case .iPad5: return [.wide]
- case .iPad6: return [.wide]
- case .iPadAir3: return [.wide]
- case .iPad7: return [.wide]
- case .iPad8: return [.wide]
- case .iPadAir4: return [.wide]
- case .iPadMini: return [.wide]
- case .iPadMini2: return [.wide]
- case .iPadMini3: return [.wide]
- case .iPadMini4: return [.wide]
- case .iPadMini5: return [.wide]
- case .iPadPro9Inch: return [.wide]
- case .iPadPro12Inch: return [.wide]
- case .iPadPro12Inch2: return [.wide]
- case .iPadPro10Inch: return [.wide]
- case .iPadPro11Inch: return [.wide]
- case .iPadPro12Inch3: return [.wide]
- case .iPhone7Plus: return [.wide, .telephoto]
- case .iPhone8Plus: return [.wide, .telephoto]
- case .iPhoneX: return [.wide, .telephoto]
- case .iPhoneXS: return [.wide, .telephoto]
- case .iPhoneXSMax: return [.wide, .telephoto]
- case .iPhone11: return [.wide, .ultraWide]
- case .iPhone12: return [.wide, .ultraWide]
- case .iPhone12Mini: return [.wide, .ultraWide]
- case .iPadPro11Inch2: return [.wide, .ultraWide]
- case .iPadPro12Inch4: return [.wide, .ultraWide]
- case .iPadPro11Inch3: return [.wide, .ultraWide]
- case .iPadPro12Inch5: return [.wide, .ultraWide]
- case .iPhone11Pro: return [.wide, .telephoto, .ultraWide]
- case .iPhone11ProMax: return [.wide, .telephoto, .ultraWide]
- case .iPhone12Pro: return [.wide, .telephoto, .ultraWide]
- case .iPhone12ProMax: 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, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// All devices that feature a normal camera
- @available(*, deprecated, renamed: "allDevicesWithWideCamera")
- public static var allDevicesWithNormalCamera: [Device] {
- return Device.allDevicesWithWideCamera
- }
- /// All devices that feature a wide camera
- public static var allDevicesWithWideCamera: [Device] {
- return [.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, .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPad5, .iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// All devices that feature a telephoto camera
- public static var allDevicesWithTelephotoCamera: [Device] {
- return [.iPhone7Plus, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax]
- }
- /// All devices that feature an ultra wide camera
- public static var allDevicesWithUltraWideCamera: [Device] {
- return [.iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
- }
- /// Returns whether or not the current device has a camera
- public var hasCamera: Bool {
- return !self.cameras.isEmpty
- }
- /// Returns whether or not the current device has a normal camera
- @available(*, deprecated, renamed: "hasWideCamera")
- public var hasNormalCamera: Bool {
- return self.hasWideCamera
- }
- /// Returns whether or not the current device has a wide camera
- public var hasWideCamera: Bool {
- return self.cameras.contains(.wide)
- }
- /// Returns whether or not the current device has a telephoto camera
- public var hasTelephotoCamera: Bool {
- return self.cameras.contains(.telephoto)
- }
- /// Returns whether or not the current device has an ultra wide camera
- public var hasUltraWideCamera: Bool {
- return self.cameras.contains(.ultraWide)
- }
- }
- #endif
|