Device.generated.swift 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the DeviceKit open source project
  4. //
  5. // Copyright © 2014 - 2018 Dennis Weissmann and the DeviceKit project authors
  6. //
  7. // License: https://github.com/dennisweissmann/DeviceKit/blob/master/LICENSE
  8. // Contributors: https://github.com/dennisweissmann/DeviceKit#contributors
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #if os(watchOS)
  12. import WatchKit
  13. #else
  14. import UIKit
  15. #endif
  16. // MARK: Device
  17. /// This enum is a value-type wrapper and extension of
  18. /// [`UIDevice`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/).
  19. ///
  20. /// Usage:
  21. ///
  22. /// let device = Device.current
  23. ///
  24. /// print(device) // prints, for example, "iPhone 6 Plus"
  25. ///
  26. /// if device == .iPhone6Plus {
  27. /// // Do something
  28. /// } else {
  29. /// // Do something else
  30. /// }
  31. ///
  32. /// ...
  33. ///
  34. /// if device.batteryState == .full || device.batteryState >= .charging(75) {
  35. /// print("Your battery is happy! 😊")
  36. /// }
  37. ///
  38. /// ...
  39. ///
  40. /// if device.batteryLevel >= 50 {
  41. /// install_iOS()
  42. /// } else {
  43. /// showError()
  44. /// }
  45. ///
  46. public enum Device {
  47. #if os(iOS)
  48. /// Device is an [iPod touch (5th generation)](https://support.apple.com/kb/SP657)
  49. ///
  50. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP657/sp657_ipod-touch_size.jpg)
  51. case iPodTouch5
  52. /// Device is an [iPod touch (6th generation)](https://support.apple.com/kb/SP720)
  53. ///
  54. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP720/SP720-ipod-touch-specs-color-sg-2015.jpg)
  55. case iPodTouch6
  56. /// Device is an [iPod touch (7th generation)](https://support.apple.com/kb/SP796)
  57. ///
  58. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP796/ipod-touch-7th-gen_2x.png)
  59. case iPodTouch7
  60. /// Device is an [iPhone 4](https://support.apple.com/kb/SP587)
  61. ///
  62. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg)
  63. case iPhone4
  64. /// Device is an [iPhone 4s](https://support.apple.com/kb/SP643)
  65. ///
  66. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP643/sp643_iphone4s_color_black.jpg)
  67. case iPhone4s
  68. /// Device is an [iPhone 5](https://support.apple.com/kb/SP655)
  69. ///
  70. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP655/sp655_iphone5_color.jpg)
  71. case iPhone5
  72. /// Device is an [iPhone 5c](https://support.apple.com/kb/SP684)
  73. ///
  74. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP684/SP684-color_yellow.jpg)
  75. case iPhone5c
  76. /// Device is an [iPhone 5s](https://support.apple.com/kb/SP685)
  77. ///
  78. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP685/SP685-color_black.jpg)
  79. case iPhone5s
  80. /// Device is an [iPhone 6](https://support.apple.com/kb/SP705)
  81. ///
  82. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP705/SP705-iphone_6-mul.png)
  83. case iPhone6
  84. /// Device is an [iPhone 6 Plus](https://support.apple.com/kb/SP706)
  85. ///
  86. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP706/SP706-iphone_6_plus-mul.png)
  87. case iPhone6Plus
  88. /// Device is an [iPhone 6s](https://support.apple.com/kb/SP726)
  89. ///
  90. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP726/SP726-iphone6s-gray-select-2015.png)
  91. case iPhone6s
  92. /// Device is an [iPhone 6s Plus](https://support.apple.com/kb/SP727)
  93. ///
  94. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP727/SP727-iphone6s-plus-gray-select-2015.png)
  95. case iPhone6sPlus
  96. /// Device is an [iPhone 7](https://support.apple.com/kb/SP743)
  97. ///
  98. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP743/iphone7-black.png)
  99. case iPhone7
  100. /// Device is an [iPhone 7 Plus](https://support.apple.com/kb/SP744)
  101. ///
  102. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP744/iphone7-plus-black.png)
  103. case iPhone7Plus
  104. /// Device is an [iPhone SE](https://support.apple.com/kb/SP738)
  105. ///
  106. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP738/SP738.png)
  107. case iPhoneSE
  108. /// Device is an [iPhone 8](https://support.apple.com/kb/SP767)
  109. ///
  110. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP767/iphone8.png)
  111. case iPhone8
  112. /// Device is an [iPhone 8 Plus](https://support.apple.com/kb/SP768)
  113. ///
  114. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP768/iphone8plus.png)
  115. case iPhone8Plus
  116. /// Device is an [iPhone X](https://support.apple.com/kb/SP770)
  117. ///
  118. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP770/iphonex.png)
  119. case iPhoneX
  120. /// Device is an [iPhone Xs](https://support.apple.com/kb/SP779)
  121. ///
  122. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP779/SP779-iphone-xs.jpg)
  123. case iPhoneXS
  124. /// Device is an [iPhone Xs Max](https://support.apple.com/kb/SP780)
  125. ///
  126. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP780/SP780-iPhone-Xs-Max.jpg)
  127. case iPhoneXSMax
  128. /// Device is an [iPhone Xʀ](https://support.apple.com/kb/SP781)
  129. ///
  130. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP781/SP781-iPhone-xr.jpg)
  131. case iPhoneXR
  132. /// Device is an [iPhone 11](https://support.apple.com/kb/SP804)
  133. ///
  134. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP804/sp804-iphone11_2x.png)
  135. case iPhone11
  136. /// Device is an [iPhone 11 Pro](https://support.apple.com/kb/SP805)
  137. ///
  138. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP805/sp805-iphone11pro_2x.png)
  139. case iPhone11Pro
  140. /// Device is an [iPhone 11 Pro Max](https://support.apple.com/kb/SP806)
  141. ///
  142. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP806/sp806-iphone11pro-max_2x.png)
  143. case iPhone11ProMax
  144. /// Device is an [iPhone SE (2nd generation)](https://support.apple.com/kb/SP820)
  145. ///
  146. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP820/iphone-se-2nd-gen_2x.png)
  147. case iPhoneSE2
  148. /// Device is an [iPhone 12](https://support.apple.com/kb/SP830)
  149. ///
  150. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP830/sp830-iphone12-ios14_2x.png)
  151. case iPhone12
  152. /// Device is an [iPhone 12 mini](https://support.apple.com/kb/SP829)
  153. ///
  154. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP829/sp829-iphone12mini-ios14_2x.png)
  155. case iPhone12Mini
  156. /// Device is an [iPhone 12 Pro](https://support.apple.com/kb/SP831)
  157. ///
  158. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP831/iphone12pro-ios14_2x.png)
  159. case iPhone12Pro
  160. /// Device is an [iPhone 12 Pro Max](https://support.apple.com/kb/SP832)
  161. ///
  162. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP832/iphone12promax-ios14_2x.png)
  163. case iPhone12ProMax
  164. /// Device is an [iPad 2](https://support.apple.com/kb/SP622)
  165. ///
  166. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP622/SP622_01-ipad2-mul.png)
  167. case iPad2
  168. /// Device is an [iPad (3rd generation)](https://support.apple.com/kb/SP647)
  169. ///
  170. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg)
  171. case iPad3
  172. /// Device is an [iPad (4th generation)](https://support.apple.com/kb/SP662)
  173. ///
  174. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP662/sp662_ipad-4th-gen_color.jpg)
  175. case iPad4
  176. /// Device is an [iPad Air](https://support.apple.com/kb/SP692)
  177. ///
  178. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP692/SP692-specs_color-mul.png)
  179. case iPadAir
  180. /// Device is an [iPad Air 2](https://support.apple.com/kb/SP708)
  181. ///
  182. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP708/SP708-space_gray.jpeg)
  183. case iPadAir2
  184. /// Device is an [iPad (5th generation)](https://support.apple.com/kb/SP751)
  185. ///
  186. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP751/ipad_5th_generation.png)
  187. case iPad5
  188. /// Device is an [iPad (6th generation)](https://support.apple.com/kb/SP774)
  189. ///
  190. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP774/sp774-ipad-6-gen_2x.png)
  191. case iPad6
  192. /// Device is an [iPad Air (3rd generation)](https://support.apple.com/kb/SP787)
  193. ///
  194. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP787/ipad-air-2019.jpg)
  195. case iPadAir3
  196. /// Device is an [iPad (7th generation)](https://support.apple.com/kb/SP807)
  197. ///
  198. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP807/sp807-ipad-7th-gen_2x.png)
  199. case iPad7
  200. /// Device is an [iPad (8th generation)](https://support.apple.com/kb/SP822)
  201. ///
  202. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP822/sp822-ipad-8gen_2x.png)
  203. case iPad8
  204. /// Device is an [iPad Air (4th generation)](https://support.apple.com/kb/SP828)
  205. ///
  206. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP828/sp828ipad-air-ipados14-960_2x.png)
  207. case iPadAir4
  208. /// Device is an [iPad Mini](https://support.apple.com/kb/SP661)
  209. ///
  210. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP661/sp661_ipad_mini_color.jpg)
  211. case iPadMini
  212. /// Device is an [iPad Mini 2](https://support.apple.com/kb/SP693)
  213. ///
  214. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP693/SP693-specs_color-mul.png)
  215. case iPadMini2
  216. /// Device is an [iPad Mini 3](https://support.apple.com/kb/SP709)
  217. ///
  218. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP709/SP709-space_gray.jpeg)
  219. case iPadMini3
  220. /// Device is an [iPad Mini 4](https://support.apple.com/kb/SP725)
  221. ///
  222. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP725/SP725ipad-mini-4.png)
  223. case iPadMini4
  224. /// Device is an [iPad Mini (5th generation)](https://support.apple.com/kb/SP788)
  225. ///
  226. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP788/ipad-mini-2019.jpg)
  227. case iPadMini5
  228. /// Device is an [iPad Pro 9.7-inch](https://support.apple.com/kb/SP739)
  229. ///
  230. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP739/SP739.png)
  231. case iPadPro9Inch
  232. /// Device is an [iPad Pro 12-inch](https://support.apple.com/kb/SP723)
  233. ///
  234. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP723/SP723-iPad_Pro_2x.png)
  235. case iPadPro12Inch
  236. /// Device is an [iPad Pro 12-inch (2nd generation)](https://support.apple.com/kb/SP761)
  237. ///
  238. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP761/ipad-pro-12in-hero-201706.png)
  239. case iPadPro12Inch2
  240. /// Device is an [iPad Pro 10.5-inch](https://support.apple.com/kb/SP762)
  241. ///
  242. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP761/ipad-pro-10in-hero-201706.png)
  243. case iPadPro10Inch
  244. /// Device is an [iPad Pro 11-inch](https://support.apple.com/kb/SP784)
  245. ///
  246. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP784/ipad-pro-11-2018_2x.png)
  247. case iPadPro11Inch
  248. /// Device is an [iPad Pro 12.9-inch (3rd generation)](https://support.apple.com/kb/SP785)
  249. ///
  250. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP785/ipad-pro-12-2018_2x.png)
  251. case iPadPro12Inch3
  252. /// Device is an [iPad Pro 11-inch (2nd generation)](https://support.apple.com/kb/SP814)
  253. ///
  254. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP814/ipad-pro-11-2020.jpeg)
  255. case iPadPro11Inch2
  256. /// Device is an [iPad Pro 12.9-inch (4th generation)](https://support.apple.com/kb/SP815)
  257. ///
  258. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP815/ipad-pro-12-2020.jpeg)
  259. case iPadPro12Inch4
  260. /// Device is an [iPad Pro 11-inch (3rd generation)](https://support.apple.com/kb/TODO)
  261. ///
  262. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/TODO)
  263. case iPadPro11Inch3
  264. /// Device is an [iPad Pro 12.9-inch (5th generation)](https://support.apple.com/kb/TODO)
  265. ///
  266. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/TODO)
  267. case iPadPro12Inch5
  268. /// Device is a [HomePod](https://support.apple.com/kb/SP773)
  269. ///
  270. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP773/homepod_space_gray_large_2x.jpg)
  271. case homePod
  272. #elseif os(tvOS)
  273. /// Device is an [Apple TV HD](https://support.apple.com/kb/SP724) (Previously Apple TV (4th generation))
  274. ///
  275. /// ![Image](http://images.apple.com/v/tv/c/images/overview/buy_tv_large_2x.jpg)
  276. case appleTVHD
  277. /// Device is an [Apple TV 4K](https://support.apple.com/kb/SP769)
  278. ///
  279. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP769/appletv4k.png)
  280. case appleTV4K
  281. /// Device is an [Apple TV 4K (2nd generation)](https://support.apple.com/kb/TODO)
  282. ///
  283. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/TODO)
  284. case appleTV4K2
  285. #elseif os(watchOS)
  286. /// Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)
  287. ///
  288. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM784/en_US/apple_watch_sport-240.png)
  289. case appleWatchSeries0_38mm
  290. /// Device is an [Apple Watch (1st generation)](https://support.apple.com/kb/SP735)
  291. ///
  292. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM784/en_US/apple_watch_sport-240.png)
  293. case appleWatchSeries0_42mm
  294. /// Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)
  295. ///
  296. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM848/en_US/applewatch-series2-aluminum-temp-240.png)
  297. case appleWatchSeries1_38mm
  298. /// Device is an [Apple Watch Series 1](https://support.apple.com/kb/SP745)
  299. ///
  300. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM848/en_US/applewatch-series2-aluminum-temp-240.png)
  301. case appleWatchSeries1_42mm
  302. /// Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)
  303. ///
  304. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM852/en_US/applewatch-series2-hermes-240.png)
  305. case appleWatchSeries2_38mm
  306. /// Device is an [Apple Watch Series 2](https://support.apple.com/kb/SP746)
  307. ///
  308. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM852/en_US/applewatch-series2-hermes-240.png)
  309. case appleWatchSeries2_42mm
  310. /// Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)
  311. ///
  312. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM893/en_US/apple-watch-s3-nikeplus-240.png)
  313. case appleWatchSeries3_38mm
  314. /// Device is an [Apple Watch Series 3](https://support.apple.com/kb/SP766)
  315. ///
  316. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM893/en_US/apple-watch-s3-nikeplus-240.png)
  317. case appleWatchSeries3_42mm
  318. /// Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)
  319. ///
  320. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM911/en_US/aw-series4-nike-240.png)
  321. case appleWatchSeries4_40mm
  322. /// Device is an [Apple Watch Series 4](https://support.apple.com/kb/SP778)
  323. ///
  324. /// ![Image](https://km.support.apple.com/resources/sites/APPLE/content/live/IMAGES/0/IM911/en_US/aw-series4-nike-240.png)
  325. case appleWatchSeries4_44mm
  326. /// Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)
  327. ///
  328. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP808/sp808-apple-watch-series-5_2x.png)
  329. case appleWatchSeries5_40mm
  330. /// Device is an [Apple Watch Series 5](https://support.apple.com/kb/SP808)
  331. ///
  332. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP808/sp808-apple-watch-series-5_2x.png)
  333. case appleWatchSeries5_44mm
  334. /// Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)
  335. ///
  336. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP826/sp826-apple-watch-series6-580_2x.png)
  337. case appleWatchSeries6_40mm
  338. /// Device is an [Apple Watch Series 6](https://support.apple.com/kb/SP826)
  339. ///
  340. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP826/sp826-apple-watch-series6-580_2x.png)
  341. case appleWatchSeries6_44mm
  342. /// Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)
  343. ///
  344. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP827/sp827-apple-watch-se-580_2x.png)
  345. case appleWatchSE_40mm
  346. /// Device is an [Apple Watch SE](https://support.apple.com/kb/SP827)
  347. ///
  348. /// ![Image](https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP827/sp827-apple-watch-se-580_2x.png)
  349. case appleWatchSE_44mm
  350. #endif
  351. /// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)
  352. ///
  353. /// ![Image](https://developer.apple.com/assets/elements/icons/256x256/xcode-6.png)
  354. indirect case simulator(Device)
  355. /// Device is not yet known (implemented)
  356. /// You can still use this enum as before but the description equals the identifier (you can get multiple identifiers for the same product class
  357. /// (e.g. "iPhone6,1" or "iPhone 6,2" do both mean "iPhone 5s"))
  358. case unknown(String)
  359. /// Returns a `Device` representing the current device this software runs on.
  360. public static var current: Device {
  361. return Device.mapToDevice(identifier: Device.identifier)
  362. }
  363. /// Gets the identifier from the system, such as "iPhone7,1".
  364. public static var identifier: String = {
  365. var systemInfo = utsname()
  366. uname(&systemInfo)
  367. let mirror = Mirror(reflecting: systemInfo.machine)
  368. let identifier = mirror.children.reduce("") { identifier, element in
  369. guard let value = element.value as? Int8, value != 0 else { return identifier }
  370. return identifier + String(UnicodeScalar(UInt8(value)))
  371. }
  372. return identifier
  373. }()
  374. /// Maps an identifier to a Device. If the identifier can not be mapped to an existing device, `UnknownDevice(identifier)` is returned.
  375. ///
  376. /// - parameter identifier: The device identifier, e.g. "iPhone7,1". Can be obtained from `Device.identifier`.
  377. ///
  378. /// - returns: An initialized `Device`.
  379. public static func mapToDevice(identifier: String) -> Device { // swiftlint:disable:this cyclomatic_complexity function_body_length
  380. #if os(iOS)
  381. switch identifier {
  382. case "iPod5,1": return iPodTouch5
  383. case "iPod7,1": return iPodTouch6
  384. case "iPod9,1": return iPodTouch7
  385. case "iPhone3,1", "iPhone3,2", "iPhone3,3": return iPhone4
  386. case "iPhone4,1": return iPhone4s
  387. case "iPhone5,1", "iPhone5,2": return iPhone5
  388. case "iPhone5,3", "iPhone5,4": return iPhone5c
  389. case "iPhone6,1", "iPhone6,2": return iPhone5s
  390. case "iPhone7,2": return iPhone6
  391. case "iPhone7,1": return iPhone6Plus
  392. case "iPhone8,1": return iPhone6s
  393. case "iPhone8,2": return iPhone6sPlus
  394. case "iPhone9,1", "iPhone9,3": return iPhone7
  395. case "iPhone9,2", "iPhone9,4": return iPhone7Plus
  396. case "iPhone8,4": return iPhoneSE
  397. case "iPhone10,1", "iPhone10,4": return iPhone8
  398. case "iPhone10,2", "iPhone10,5": return iPhone8Plus
  399. case "iPhone10,3", "iPhone10,6": return iPhoneX
  400. case "iPhone11,2": return iPhoneXS
  401. case "iPhone11,4", "iPhone11,6": return iPhoneXSMax
  402. case "iPhone11,8": return iPhoneXR
  403. case "iPhone12,1": return iPhone11
  404. case "iPhone12,3": return iPhone11Pro
  405. case "iPhone12,5": return iPhone11ProMax
  406. case "iPhone12,8": return iPhoneSE2
  407. case "iPhone13,2": return iPhone12
  408. case "iPhone13,1": return iPhone12Mini
  409. case "iPhone13,3": return iPhone12Pro
  410. case "iPhone13,4": return iPhone12ProMax
  411. case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return iPad2
  412. case "iPad3,1", "iPad3,2", "iPad3,3": return iPad3
  413. case "iPad3,4", "iPad3,5", "iPad3,6": return iPad4
  414. case "iPad4,1", "iPad4,2", "iPad4,3": return iPadAir
  415. case "iPad5,3", "iPad5,4": return iPadAir2
  416. case "iPad6,11", "iPad6,12": return iPad5
  417. case "iPad7,5", "iPad7,6": return iPad6
  418. case "iPad11,3", "iPad11,4": return iPadAir3
  419. case "iPad7,11", "iPad7,12": return iPad7
  420. case "iPad11,6", "iPad11,7": return iPad8
  421. case "iPad13,1", "iPad13,2": return iPadAir4
  422. case "iPad2,5", "iPad2,6", "iPad2,7": return iPadMini
  423. case "iPad4,4", "iPad4,5", "iPad4,6": return iPadMini2
  424. case "iPad4,7", "iPad4,8", "iPad4,9": return iPadMini3
  425. case "iPad5,1", "iPad5,2": return iPadMini4
  426. case "iPad11,1", "iPad11,2": return iPadMini5
  427. case "iPad6,3", "iPad6,4": return iPadPro9Inch
  428. case "iPad6,7", "iPad6,8": return iPadPro12Inch
  429. case "iPad7,1", "iPad7,2": return iPadPro12Inch2
  430. case "iPad7,3", "iPad7,4": return iPadPro10Inch
  431. case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4": return iPadPro11Inch
  432. case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8": return iPadPro12Inch3
  433. case "iPad8,9", "iPad8,10": return iPadPro11Inch2
  434. case "iPad8,11", "iPad8,12": return iPadPro12Inch4
  435. case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7": return iPadPro11Inch3
  436. case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": return iPadPro12Inch5
  437. case "AudioAccessory1,1": return homePod
  438. case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))
  439. default: return unknown(identifier)
  440. }
  441. #elseif os(tvOS)
  442. switch identifier {
  443. case "AppleTV5,3": return appleTVHD
  444. case "AppleTV6,2": return appleTV4K
  445. case "AppleTV11,1": return appleTV4K2
  446. case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))
  447. default: return unknown(identifier)
  448. }
  449. #elseif os(watchOS)
  450. switch identifier {
  451. case "Watch1,1": return appleWatchSeries0_38mm
  452. case "Watch1,2": return appleWatchSeries0_42mm
  453. case "Watch2,6": return appleWatchSeries1_38mm
  454. case "Watch2,7": return appleWatchSeries1_42mm
  455. case "Watch2,3": return appleWatchSeries2_38mm
  456. case "Watch2,4": return appleWatchSeries2_42mm
  457. case "Watch3,1", "Watch3,3": return appleWatchSeries3_38mm
  458. case "Watch3,2", "Watch3,4": return appleWatchSeries3_42mm
  459. case "Watch4,1", "Watch4,3": return appleWatchSeries4_40mm
  460. case "Watch4,2", "Watch4,4": return appleWatchSeries4_44mm
  461. case "Watch5,1", "Watch5,3": return appleWatchSeries5_40mm
  462. case "Watch5,2", "Watch5,4": return appleWatchSeries5_44mm
  463. case "Watch6,1", "Watch6,3": return appleWatchSeries6_40mm
  464. case "Watch6,2", "Watch6,4": return appleWatchSeries6_44mm
  465. case "Watch5,9", "Watch5,11": return appleWatchSE_40mm
  466. case "Watch5,10", "Watch5,12": return appleWatchSE_44mm
  467. case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "watchOS"))
  468. default: return unknown(identifier)
  469. }
  470. #endif
  471. }
  472. /// Get the real device from a device.
  473. /// If the device is a an iPhone8Plus simulator this function returns .iPhone8Plus (the real device).
  474. /// If the parameter is a real device, this function returns just that passed parameter.
  475. ///
  476. /// - parameter device: A device.
  477. ///
  478. /// - returns: the underlying device If the `device` is a `simulator`,
  479. /// otherwise return the `device`.
  480. public static func realDevice(from device: Device) -> Device {
  481. if case let .simulator(model) = device {
  482. return model
  483. }
  484. return device
  485. }
  486. #if os(iOS) || os(watchOS)
  487. /// Returns diagonal screen length in inches
  488. public var diagonal: Double {
  489. #if os(iOS)
  490. switch self {
  491. case .iPodTouch5: return 4
  492. case .iPodTouch6: return 4
  493. case .iPodTouch7: return 4
  494. case .iPhone4: return 3.5
  495. case .iPhone4s: return 3.5
  496. case .iPhone5: return 4
  497. case .iPhone5c: return 4
  498. case .iPhone5s: return 4
  499. case .iPhone6: return 4.7
  500. case .iPhone6Plus: return 5.5
  501. case .iPhone6s: return 4.7
  502. case .iPhone6sPlus: return 5.5
  503. case .iPhone7: return 4.7
  504. case .iPhone7Plus: return 5.5
  505. case .iPhoneSE: return 4
  506. case .iPhone8: return 4.7
  507. case .iPhone8Plus: return 5.5
  508. case .iPhoneX: return 5.8
  509. case .iPhoneXS: return 5.8
  510. case .iPhoneXSMax: return 6.5
  511. case .iPhoneXR: return 6.1
  512. case .iPhone11: return 6.1
  513. case .iPhone11Pro: return 5.8
  514. case .iPhone11ProMax: return 6.5
  515. case .iPhoneSE2: return 4.7
  516. case .iPhone12: return 6.1
  517. case .iPhone12Mini: return 5.4
  518. case .iPhone12Pro: return 6.1
  519. case .iPhone12ProMax: return 6.7
  520. case .iPad2: return 9.7
  521. case .iPad3: return 9.7
  522. case .iPad4: return 9.7
  523. case .iPadAir: return 9.7
  524. case .iPadAir2: return 9.7
  525. case .iPad5: return 9.7
  526. case .iPad6: return 9.7
  527. case .iPadAir3: return 10.5
  528. case .iPad7: return 10.2
  529. case .iPad8: return 10.2
  530. case .iPadAir4: return 10.9
  531. case .iPadMini: return 7.9
  532. case .iPadMini2: return 7.9
  533. case .iPadMini3: return 7.9
  534. case .iPadMini4: return 7.9
  535. case .iPadMini5: return 7.9
  536. case .iPadPro9Inch: return 9.7
  537. case .iPadPro12Inch: return 12.9
  538. case .iPadPro12Inch2: return 12.9
  539. case .iPadPro10Inch: return 10.5
  540. case .iPadPro11Inch: return 11.0
  541. case .iPadPro12Inch3: return 12.9
  542. case .iPadPro11Inch2: return 11.0
  543. case .iPadPro12Inch4: return 12.9
  544. case .iPadPro11Inch3: return 11.0
  545. case .iPadPro12Inch5: return 12.9
  546. case .homePod: return -1
  547. case .simulator(let model): return model.diagonal
  548. case .unknown: return -1
  549. }
  550. #elseif os(watchOS)
  551. switch self {
  552. case .appleWatchSeries0_38mm: return 1.5
  553. case .appleWatchSeries0_42mm: return 1.6
  554. case .appleWatchSeries1_38mm: return 1.5
  555. case .appleWatchSeries1_42mm: return 1.6
  556. case .appleWatchSeries2_38mm: return 1.5
  557. case .appleWatchSeries2_42mm: return 1.6
  558. case .appleWatchSeries3_38mm: return 1.5
  559. case .appleWatchSeries3_42mm: return 1.6
  560. case .appleWatchSeries4_40mm: return 1.8
  561. case .appleWatchSeries4_44mm: return 2.0
  562. case .appleWatchSeries5_40mm: return 1.8
  563. case .appleWatchSeries5_44mm: return 2.0
  564. case .appleWatchSeries6_40mm: return 1.8
  565. case .appleWatchSeries6_44mm: return 2.0
  566. case .appleWatchSE_40mm: return 1.8
  567. case .appleWatchSE_44mm: return 2.0
  568. case .simulator(let model): return model.diagonal
  569. case .unknown: return -1
  570. }
  571. #endif
  572. }
  573. #endif
  574. /// Returns screen ratio as a tuple
  575. public var screenRatio: (width: Double, height: Double) {
  576. #if os(iOS)
  577. switch self {
  578. case .iPodTouch5: return (width: 9, height: 16)
  579. case .iPodTouch6: return (width: 9, height: 16)
  580. case .iPodTouch7: return (width: 9, height: 16)
  581. case .iPhone4: return (width: 2, height: 3)
  582. case .iPhone4s: return (width: 2, height: 3)
  583. case .iPhone5: return (width: 9, height: 16)
  584. case .iPhone5c: return (width: 9, height: 16)
  585. case .iPhone5s: return (width: 9, height: 16)
  586. case .iPhone6: return (width: 9, height: 16)
  587. case .iPhone6Plus: return (width: 9, height: 16)
  588. case .iPhone6s: return (width: 9, height: 16)
  589. case .iPhone6sPlus: return (width: 9, height: 16)
  590. case .iPhone7: return (width: 9, height: 16)
  591. case .iPhone7Plus: return (width: 9, height: 16)
  592. case .iPhoneSE: return (width: 9, height: 16)
  593. case .iPhone8: return (width: 9, height: 16)
  594. case .iPhone8Plus: return (width: 9, height: 16)
  595. case .iPhoneX: return (width: 9, height: 19.5)
  596. case .iPhoneXS: return (width: 9, height: 19.5)
  597. case .iPhoneXSMax: return (width: 9, height: 19.5)
  598. case .iPhoneXR: return (width: 9, height: 19.5)
  599. case .iPhone11: return (width: 9, height: 19.5)
  600. case .iPhone11Pro: return (width: 9, height: 19.5)
  601. case .iPhone11ProMax: return (width: 9, height: 19.5)
  602. case .iPhoneSE2: return (width: 9, height: 16)
  603. case .iPhone12: return (width: 9, height: 19.5)
  604. case .iPhone12Mini: return (width: 9, height: 19.5)
  605. case .iPhone12Pro: return (width: 9, height: 19.5)
  606. case .iPhone12ProMax: return (width: 9, height: 19.5)
  607. case .iPad2: return (width: 3, height: 4)
  608. case .iPad3: return (width: 3, height: 4)
  609. case .iPad4: return (width: 3, height: 4)
  610. case .iPadAir: return (width: 3, height: 4)
  611. case .iPadAir2: return (width: 3, height: 4)
  612. case .iPad5: return (width: 3, height: 4)
  613. case .iPad6: return (width: 3, height: 4)
  614. case .iPadAir3: return (width: 3, height: 4)
  615. case .iPad7: return (width: 3, height: 4)
  616. case .iPad8: return (width: 3, height: 4)
  617. case .iPadAir4: return (width: 41, height: 59)
  618. case .iPadMini: return (width: 3, height: 4)
  619. case .iPadMini2: return (width: 3, height: 4)
  620. case .iPadMini3: return (width: 3, height: 4)
  621. case .iPadMini4: return (width: 3, height: 4)
  622. case .iPadMini5: return (width: 3, height: 4)
  623. case .iPadPro9Inch: return (width: 3, height: 4)
  624. case .iPadPro12Inch: return (width: 3, height: 4)
  625. case .iPadPro12Inch2: return (width: 3, height: 4)
  626. case .iPadPro10Inch: return (width: 3, height: 4)
  627. case .iPadPro11Inch: return (width: 139, height: 199)
  628. case .iPadPro12Inch3: return (width: 512, height: 683)
  629. case .iPadPro11Inch2: return (width: 139, height: 199)
  630. case .iPadPro12Inch4: return (width: 512, height: 683)
  631. case .iPadPro11Inch3: return (width: 139, height: 199)
  632. case .iPadPro12Inch5: return (width: 512, height: 683)
  633. case .homePod: return (width: 4, height: 5)
  634. case .simulator(let model): return model.screenRatio
  635. case .unknown: return (width: -1, height: -1)
  636. }
  637. #elseif os(watchOS)
  638. switch self {
  639. case .appleWatchSeries0_38mm: return (width: 4, height: 5)
  640. case .appleWatchSeries0_42mm: return (width: 4, height: 5)
  641. case .appleWatchSeries1_38mm: return (width: 4, height: 5)
  642. case .appleWatchSeries1_42mm: return (width: 4, height: 5)
  643. case .appleWatchSeries2_38mm: return (width: 4, height: 5)
  644. case .appleWatchSeries2_42mm: return (width: 4, height: 5)
  645. case .appleWatchSeries3_38mm: return (width: 4, height: 5)
  646. case .appleWatchSeries3_42mm: return (width: 4, height: 5)
  647. case .appleWatchSeries4_40mm: return (width: 4, height: 5)
  648. case .appleWatchSeries4_44mm: return (width: 4, height: 5)
  649. case .appleWatchSeries5_40mm: return (width: 4, height: 5)
  650. case .appleWatchSeries5_44mm: return (width: 4, height: 5)
  651. case .appleWatchSeries6_40mm: return (width: 4, height: 5)
  652. case .appleWatchSeries6_44mm: return (width: 4, height: 5)
  653. case .appleWatchSE_40mm: return (width: 4, height: 5)
  654. case .appleWatchSE_44mm: return (width: 4, height: 5)
  655. case .simulator(let model): return model.screenRatio
  656. case .unknown: return (width: -1, height: -1)
  657. }
  658. #elseif os(tvOS)
  659. return (width: -1, height: -1)
  660. #endif
  661. }
  662. #if os(iOS)
  663. /// All iPods
  664. public static var allPods: [Device] {
  665. return [.iPodTouch5, .iPodTouch6, .iPodTouch7]
  666. }
  667. /// All iPhones
  668. public static var allPhones: [Device] {
  669. 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]
  670. }
  671. /// All iPads
  672. public static var allPads: [Device] {
  673. 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]
  674. }
  675. /// All X-Series Devices
  676. @available(*, deprecated, renamed: "allDevicesWithSensorHousing")
  677. public static var allXSeriesDevices: [Device] {
  678. return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax]
  679. }
  680. /// All Plus and Max-Sized Devices
  681. public static var allPlusSizedDevices: [Device] {
  682. return [.iPhone6Plus, .iPhone6sPlus, .iPhone7Plus, .iPhone8Plus, .iPhoneXSMax, .iPhone11ProMax, .iPhone12ProMax]
  683. }
  684. /// All Pro Devices
  685. public static var allProDevices: [Device] {
  686. return [.iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  687. }
  688. /// All mini Devices
  689. public static var allMiniDevices: [Device] {
  690. return [.iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadMini5]
  691. }
  692. /// All simulator iPods
  693. public static var allSimulatorPods: [Device] {
  694. return allPods.map(Device.simulator)
  695. }
  696. /// All simulator iPhones
  697. public static var allSimulatorPhones: [Device] {
  698. return allPhones.map(Device.simulator)
  699. }
  700. /// All simulator iPads
  701. public static var allSimulatorPads: [Device] {
  702. return allPads.map(Device.simulator)
  703. }
  704. /// All simulator iPad mini
  705. public static var allSimulatorMiniDevices: [Device] {
  706. return allMiniDevices.map(Device.simulator)
  707. }
  708. /// All simulator X series Devices
  709. @available(*, deprecated, renamed: "allSimulatorDevicesWithSensorHousing")
  710. public static var allSimulatorXSeriesDevices: [Device] {
  711. return allDevicesWithSensorHousing.map(Device.simulator)
  712. }
  713. /// All simulator Plus and Max-Sized Devices
  714. public static var allSimulatorPlusSizedDevices: [Device] {
  715. return allPlusSizedDevices.map(Device.simulator)
  716. }
  717. /// All simulator Pro Devices
  718. public static var allSimulatorProDevices: [Device] {
  719. return allProDevices.map(Device.simulator)
  720. }
  721. /// Returns whether the device is an iPod (real or simulator)
  722. public var isPod: Bool {
  723. return isOneOf(Device.allPods) || isOneOf(Device.allSimulatorPods)
  724. }
  725. /// Returns whether the device is an iPhone (real or simulator)
  726. public var isPhone: Bool {
  727. return (isOneOf(Device.allPhones)
  728. || isOneOf(Device.allSimulatorPhones)
  729. || (UIDevice.current.userInterfaceIdiom == .phone && isCurrent)) && !isPod
  730. }
  731. /// Returns whether the device is an iPad (real or simulator)
  732. public var isPad: Bool {
  733. return isOneOf(Device.allPads)
  734. || isOneOf(Device.allSimulatorPads)
  735. || (UIDevice.current.userInterfaceIdiom == .pad && isCurrent)
  736. }
  737. /// Returns whether the device is any of the simulator
  738. /// Useful when there is a need to check and skip running a portion of code (location request or others)
  739. public var isSimulator: Bool {
  740. return isOneOf(Device.allSimulators)
  741. }
  742. /// If this device is a simulator return the underlying device,
  743. /// otherwise return `self`.
  744. public var realDevice: Device {
  745. return Device.realDevice(from: self)
  746. }
  747. public var isZoomed: Bool? {
  748. guard isCurrent else { return nil }
  749. if Int(UIScreen.main.scale.rounded()) == 3 {
  750. // Plus-sized
  751. return UIScreen.main.nativeScale > 2.7 && UIScreen.main.nativeScale < 3
  752. } else {
  753. return UIScreen.main.nativeScale > UIScreen.main.scale
  754. }
  755. }
  756. /// All Touch ID Capable Devices
  757. public static var allTouchIDCapableDevices: [Device] {
  758. 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]
  759. }
  760. /// All Face ID Capable Devices
  761. public static var allFaceIDCapableDevices: [Device] {
  762. return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  763. }
  764. /// All Devices with Touch ID or Face ID
  765. public static var allBiometricAuthenticationCapableDevices: [Device] {
  766. 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]
  767. }
  768. /// Returns whether or not the device has Touch ID
  769. public var isTouchIDCapable: Bool {
  770. return isOneOf(Device.allTouchIDCapableDevices) || isOneOf(Device.allTouchIDCapableDevices.map(Device.simulator))
  771. }
  772. /// Returns whether or not the device has Face ID
  773. public var isFaceIDCapable: Bool {
  774. return isOneOf(Device.allFaceIDCapableDevices) || isOneOf(Device.allFaceIDCapableDevices.map(Device.simulator))
  775. }
  776. /// Returns whether or not the device has any biometric sensor (i.e. Touch ID or Face ID)
  777. public var hasBiometricSensor: Bool {
  778. return isTouchIDCapable || isFaceIDCapable
  779. }
  780. /// All devices that feature a sensor housing in the screen
  781. public static var allDevicesWithSensorHousing: [Device] {
  782. return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax]
  783. }
  784. /// All simulator devices that feature a sensor housing in the screen
  785. public static var allSimulatorDevicesWithSensorHousing: [Device] {
  786. return allDevicesWithSensorHousing.map(Device.simulator)
  787. }
  788. /// Returns whether or not the device has a sensor housing
  789. public var hasSensorHousing: Bool {
  790. return isOneOf(Device.allDevicesWithSensorHousing) || isOneOf(Device.allDevicesWithSensorHousing.map(Device.simulator))
  791. }
  792. /// All devices that feature a screen with rounded corners.
  793. public static var allDevicesWithRoundedDisplayCorners: [Device] {
  794. return [.iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadAir4, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  795. }
  796. /// Returns whether or not the device has a screen with rounded corners.
  797. public var hasRoundedDisplayCorners: Bool {
  798. return isOneOf(Device.allDevicesWithRoundedDisplayCorners) || isOneOf(Device.allDevicesWithRoundedDisplayCorners.map(Device.simulator))
  799. }
  800. /// All devices that have 3D Touch support.
  801. public static var allDevicesWith3dTouchSupport: [Device] {
  802. return [.iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax]
  803. }
  804. /// Returns whether or not the device has 3D Touch support.
  805. public var has3dTouchSupport: Bool {
  806. return isOneOf(Device.allDevicesWith3dTouchSupport) || isOneOf(Device.allDevicesWith3dTouchSupport.map(Device.simulator))
  807. }
  808. /// All devices that support wireless charging.
  809. public static var allDevicesWithWirelessChargingSupport: [Device] {
  810. return [.iPhone8, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhoneXR, .iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhoneSE2, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax]
  811. }
  812. /// Returns whether or not the device supports wireless charging.
  813. public var supportsWirelessCharging: Bool {
  814. return isOneOf(Device.allDevicesWithWirelessChargingSupport) || isOneOf(Device.allDevicesWithWirelessChargingSupport.map(Device.simulator))
  815. }
  816. /// All devices that have a LiDAR sensor.
  817. public static var allDevicesWithALidarSensor: [Device] {
  818. return [.iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  819. }
  820. /// Returns whether or not the device has a LiDAR sensor.
  821. public var hasLidarSensor: Bool {
  822. return isOneOf(Device.allDevicesWithALidarSensor) || isOneOf(Device.allDevicesWithALidarSensor.map(Device.simulator))
  823. }
  824. #elseif os(tvOS)
  825. /// All TVs
  826. public static var allTVs: [Device] {
  827. return [.appleTVHD, .appleTV4K, .appleTV4K2]
  828. }
  829. /// All simulator TVs
  830. public static var allSimulatorTVs: [Device] {
  831. return allTVs.map(Device.simulator)
  832. }
  833. #elseif os(watchOS)
  834. /// All Watches
  835. public static var allWatches: [Device] {
  836. 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]
  837. }
  838. /// All simulator Watches
  839. public static var allSimulatorWatches: [Device] {
  840. return allWatches.map(Device.simulator)
  841. }
  842. /// All watches that have Force Touch support.
  843. public static var allWatchesWithForceTouchSupport: [Device] {
  844. 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]
  845. }
  846. /// Returns whether or not the device has Force Touch support.
  847. public var hasForceTouchSupport: Bool {
  848. return isOneOf(Device.allWatchesWithForceTouchSupport) || isOneOf(Device.allWatchesWithForceTouchSupport.map(Device.simulator))
  849. }
  850. #endif
  851. /// All real devices (i.e. all devices except for all simulators)
  852. public static var allRealDevices: [Device] {
  853. #if os(iOS)
  854. return allPods + allPhones + allPads
  855. #elseif os(tvOS)
  856. return allTVs
  857. #elseif os(watchOS)
  858. return allWatches
  859. #endif
  860. }
  861. /// All simulators
  862. public static var allSimulators: [Device] {
  863. return allRealDevices.map(Device.simulator)
  864. }
  865. /**
  866. This method saves you in many cases from the need of updating your code with every new device.
  867. Most uses for an enum like this are the following:
  868. ```
  869. switch Device.current {
  870. case .iPodTouch5, .iPodTouch6: callMethodOnIPods()
  871. case .iPhone4, iPhone4s, .iPhone5, .iPhone5s, .iPhone6, .iPhone6Plus, .iPhone6s, .iPhone6sPlus, .iPhone7, .iPhone7Plus, .iPhoneSE, .iPhone8, .iPhone8Plus, .iPhoneX: callMethodOnIPhones()
  872. case .iPad2, .iPad3, .iPad4, .iPadAir, .iPadAir2, .iPadMini, .iPadMini2, .iPadMini3, .iPadMini4, .iPadPro: callMethodOnIPads()
  873. default: break
  874. }
  875. ```
  876. This code can now be replaced with
  877. ```
  878. let device = Device.current
  879. if device.isOneOf(Device.allPods) {
  880. callMethodOnIPods()
  881. } else if device.isOneOf(Device.allPhones) {
  882. callMethodOnIPhones()
  883. } else if device.isOneOf(Device.allPads) {
  884. callMethodOnIPads()
  885. }
  886. ```
  887. - parameter devices: An array of devices.
  888. - returns: Returns whether the current device is one of the passed in ones.
  889. */
  890. public func isOneOf(_ devices: [Device]) -> Bool {
  891. return devices.contains(self)
  892. }
  893. // MARK: Current Device
  894. /// Whether or not the current device is the current device.
  895. private var isCurrent: Bool {
  896. return self == Device.current
  897. }
  898. /// The name identifying the device (e.g. "Dennis' iPhone").
  899. public var name: String? {
  900. guard isCurrent else { return nil }
  901. #if os(watchOS)
  902. return WKInterfaceDevice.current().name
  903. #else
  904. return UIDevice.current.name
  905. #endif
  906. }
  907. /// The name of the operating system running on the device represented by the receiver (e.g. "iOS" or "tvOS").
  908. public var systemName: String? {
  909. guard isCurrent else { return nil }
  910. #if os(watchOS)
  911. return WKInterfaceDevice.current().systemName
  912. #else
  913. return UIDevice.current.systemName
  914. #endif
  915. }
  916. /// The current version of the operating system (e.g. 8.4 or 9.2).
  917. public var systemVersion: String? {
  918. guard isCurrent else { return nil }
  919. #if os(watchOS)
  920. return WKInterfaceDevice.current().systemVersion
  921. #else
  922. return UIDevice.current.systemVersion
  923. #endif
  924. }
  925. /// The model of the device (e.g. "iPhone" or "iPod Touch").
  926. public var model: String? {
  927. guard isCurrent else { return nil }
  928. #if os(watchOS)
  929. return WKInterfaceDevice.current().model
  930. #else
  931. return UIDevice.current.model
  932. #endif
  933. }
  934. /// The model of the device as a localized string.
  935. public var localizedModel: String? {
  936. guard isCurrent else { return nil }
  937. #if os(watchOS)
  938. return WKInterfaceDevice.current().localizedModel
  939. #else
  940. return UIDevice.current.localizedModel
  941. #endif
  942. }
  943. /// PPI (Pixels per Inch) on the current device's screen (if applicable). When the device is not applicable this property returns nil.
  944. public var ppi: Int? {
  945. #if os(iOS)
  946. switch self {
  947. case .iPodTouch5: return 326
  948. case .iPodTouch6: return 326
  949. case .iPodTouch7: return 326
  950. case .iPhone4: return 326
  951. case .iPhone4s: return 326
  952. case .iPhone5: return 326
  953. case .iPhone5c: return 326
  954. case .iPhone5s: return 326
  955. case .iPhone6: return 326
  956. case .iPhone6Plus: return 401
  957. case .iPhone6s: return 326
  958. case .iPhone6sPlus: return 401
  959. case .iPhone7: return 326
  960. case .iPhone7Plus: return 401
  961. case .iPhoneSE: return 326
  962. case .iPhone8: return 326
  963. case .iPhone8Plus: return 401
  964. case .iPhoneX: return 458
  965. case .iPhoneXS: return 458
  966. case .iPhoneXSMax: return 458
  967. case .iPhoneXR: return 326
  968. case .iPhone11: return 326
  969. case .iPhone11Pro: return 458
  970. case .iPhone11ProMax: return 458
  971. case .iPhoneSE2: return 326
  972. case .iPhone12: return 460
  973. case .iPhone12Mini: return 476
  974. case .iPhone12Pro: return 460
  975. case .iPhone12ProMax: return 458
  976. case .iPad2: return 132
  977. case .iPad3: return 264
  978. case .iPad4: return 264
  979. case .iPadAir: return 264
  980. case .iPadAir2: return 264
  981. case .iPad5: return 264
  982. case .iPad6: return 264
  983. case .iPadAir3: return 264
  984. case .iPad7: return 264
  985. case .iPad8: return 264
  986. case .iPadAir4: return 264
  987. case .iPadMini: return 163
  988. case .iPadMini2: return 326
  989. case .iPadMini3: return 326
  990. case .iPadMini4: return 326
  991. case .iPadMini5: return 326
  992. case .iPadPro9Inch: return 264
  993. case .iPadPro12Inch: return 264
  994. case .iPadPro12Inch2: return 264
  995. case .iPadPro10Inch: return 264
  996. case .iPadPro11Inch: return 264
  997. case .iPadPro12Inch3: return 264
  998. case .iPadPro11Inch2: return 264
  999. case .iPadPro12Inch4: return 264
  1000. case .iPadPro11Inch3: return 264
  1001. case .iPadPro12Inch5: return 264
  1002. case .homePod: return -1
  1003. case .simulator(let model): return model.ppi
  1004. case .unknown: return nil
  1005. }
  1006. #elseif os(watchOS)
  1007. switch self {
  1008. case .appleWatchSeries0_38mm: return 290
  1009. case .appleWatchSeries0_42mm: return 303
  1010. case .appleWatchSeries1_38mm: return 290
  1011. case .appleWatchSeries1_42mm: return 303
  1012. case .appleWatchSeries2_38mm: return 290
  1013. case .appleWatchSeries2_42mm: return 303
  1014. case .appleWatchSeries3_38mm: return 290
  1015. case .appleWatchSeries3_42mm: return 303
  1016. case .appleWatchSeries4_40mm: return 326
  1017. case .appleWatchSeries4_44mm: return 326
  1018. case .appleWatchSeries5_40mm: return 326
  1019. case .appleWatchSeries5_44mm: return 326
  1020. case .appleWatchSeries6_40mm: return 326
  1021. case .appleWatchSeries6_44mm: return 326
  1022. case .appleWatchSE_40mm: return 326
  1023. case .appleWatchSE_44mm: return 326
  1024. case .simulator(let model): return model.ppi
  1025. case .unknown: return nil
  1026. }
  1027. #elseif os(tvOS)
  1028. return nil
  1029. #endif
  1030. }
  1031. /// True when a Guided Access session is currently active; otherwise, false.
  1032. public var isGuidedAccessSessionActive: Bool {
  1033. #if os(iOS)
  1034. #if swift(>=4.2)
  1035. return UIAccessibility.isGuidedAccessEnabled
  1036. #else
  1037. return UIAccessibilityIsGuidedAccessEnabled()
  1038. #endif
  1039. #else
  1040. return false
  1041. #endif
  1042. }
  1043. /// The brightness level of the screen.
  1044. public var screenBrightness: Int {
  1045. #if os(iOS)
  1046. return Int(UIScreen.main.brightness * 100)
  1047. #else
  1048. return 100
  1049. #endif
  1050. }
  1051. }
  1052. // MARK: CustomStringConvertible
  1053. extension Device: CustomStringConvertible {
  1054. /// A textual representation of the device.
  1055. public var description: String {
  1056. #if os(iOS)
  1057. switch self {
  1058. case .iPodTouch5: return "iPod touch (5th generation)"
  1059. case .iPodTouch6: return "iPod touch (6th generation)"
  1060. case .iPodTouch7: return "iPod touch (7th generation)"
  1061. case .iPhone4: return "iPhone 4"
  1062. case .iPhone4s: return "iPhone 4s"
  1063. case .iPhone5: return "iPhone 5"
  1064. case .iPhone5c: return "iPhone 5c"
  1065. case .iPhone5s: return "iPhone 5s"
  1066. case .iPhone6: return "iPhone 6"
  1067. case .iPhone6Plus: return "iPhone 6 Plus"
  1068. case .iPhone6s: return "iPhone 6s"
  1069. case .iPhone6sPlus: return "iPhone 6s Plus"
  1070. case .iPhone7: return "iPhone 7"
  1071. case .iPhone7Plus: return "iPhone 7 Plus"
  1072. case .iPhoneSE: return "iPhone SE"
  1073. case .iPhone8: return "iPhone 8"
  1074. case .iPhone8Plus: return "iPhone 8 Plus"
  1075. case .iPhoneX: return "iPhone X"
  1076. case .iPhoneXS: return "iPhone Xs"
  1077. case .iPhoneXSMax: return "iPhone Xs Max"
  1078. case .iPhoneXR: return "iPhone Xʀ"
  1079. case .iPhone11: return "iPhone 11"
  1080. case .iPhone11Pro: return "iPhone 11 Pro"
  1081. case .iPhone11ProMax: return "iPhone 11 Pro Max"
  1082. case .iPhoneSE2: return "iPhone SE (2nd generation)"
  1083. case .iPhone12: return "iPhone 12"
  1084. case .iPhone12Mini: return "iPhone 12 mini"
  1085. case .iPhone12Pro: return "iPhone 12 Pro"
  1086. case .iPhone12ProMax: return "iPhone 12 Pro Max"
  1087. case .iPad2: return "iPad 2"
  1088. case .iPad3: return "iPad (3rd generation)"
  1089. case .iPad4: return "iPad (4th generation)"
  1090. case .iPadAir: return "iPad Air"
  1091. case .iPadAir2: return "iPad Air 2"
  1092. case .iPad5: return "iPad (5th generation)"
  1093. case .iPad6: return "iPad (6th generation)"
  1094. case .iPadAir3: return "iPad Air (3rd generation)"
  1095. case .iPad7: return "iPad (7th generation)"
  1096. case .iPad8: return "iPad (8th generation)"
  1097. case .iPadAir4: return "iPad Air (4th generation)"
  1098. case .iPadMini: return "iPad Mini"
  1099. case .iPadMini2: return "iPad Mini 2"
  1100. case .iPadMini3: return "iPad Mini 3"
  1101. case .iPadMini4: return "iPad Mini 4"
  1102. case .iPadMini5: return "iPad Mini (5th generation)"
  1103. case .iPadPro9Inch: return "iPad Pro (9.7-inch)"
  1104. case .iPadPro12Inch: return "iPad Pro (12.9-inch)"
  1105. case .iPadPro12Inch2: return "iPad Pro (12.9-inch) (2nd generation)"
  1106. case .iPadPro10Inch: return "iPad Pro (10.5-inch)"
  1107. case .iPadPro11Inch: return "iPad Pro (11-inch)"
  1108. case .iPadPro12Inch3: return "iPad Pro (12.9-inch) (3rd generation)"
  1109. case .iPadPro11Inch2: return "iPad Pro (11-inch) (2nd generation)"
  1110. case .iPadPro12Inch4: return "iPad Pro (12.9-inch) (4th generation)"
  1111. case .iPadPro11Inch3: return "iPad Pro (11-inch) (3rd generation)"
  1112. case .iPadPro12Inch5: return "iPad Pro (12.9-inch) (5th generation)"
  1113. case .homePod: return "HomePod"
  1114. case .simulator(let model): return "Simulator (\(model.description))"
  1115. case .unknown(let identifier): return identifier
  1116. }
  1117. #elseif os(watchOS)
  1118. switch self {
  1119. case .appleWatchSeries0_38mm: return "Apple Watch (1st generation) 38mm"
  1120. case .appleWatchSeries0_42mm: return "Apple Watch (1st generation) 42mm"
  1121. case .appleWatchSeries1_38mm: return "Apple Watch Series 1 38mm"
  1122. case .appleWatchSeries1_42mm: return "Apple Watch Series 1 42mm"
  1123. case .appleWatchSeries2_38mm: return "Apple Watch Series 2 38mm"
  1124. case .appleWatchSeries2_42mm: return "Apple Watch Series 2 42mm"
  1125. case .appleWatchSeries3_38mm: return "Apple Watch Series 3 38mm"
  1126. case .appleWatchSeries3_42mm: return "Apple Watch Series 3 42mm"
  1127. case .appleWatchSeries4_40mm: return "Apple Watch Series 4 40mm"
  1128. case .appleWatchSeries4_44mm: return "Apple Watch Series 4 44mm"
  1129. case .appleWatchSeries5_40mm: return "Apple Watch Series 5 40mm"
  1130. case .appleWatchSeries5_44mm: return "Apple Watch Series 5 44mm"
  1131. case .appleWatchSeries6_40mm: return "Apple Watch Series 6 40mm"
  1132. case .appleWatchSeries6_44mm: return "Apple Watch Series 6 44mm"
  1133. case .appleWatchSE_40mm: return "Apple Watch SE 40mm"
  1134. case .appleWatchSE_44mm: return "Apple Watch SE 44mm"
  1135. case .simulator(let model): return "Simulator (\(model.description))"
  1136. case .unknown(let identifier): return identifier
  1137. }
  1138. #elseif os(tvOS)
  1139. switch self {
  1140. case .appleTVHD: return "Apple TV HD"
  1141. case .appleTV4K: return "Apple TV 4K"
  1142. case .appleTV4K2: return "Apple TV 4K (2nd generation)"
  1143. case .simulator(let model): return "Simulator (\(model.description))"
  1144. case .unknown(let identifier): return identifier
  1145. }
  1146. #endif
  1147. }
  1148. /// A safe version of `description`.
  1149. /// Example:
  1150. /// Device.iPhoneXR.description: iPhone Xʀ
  1151. /// Device.iPhoneXR.safeDescription: iPhone XR
  1152. public var safeDescription: String {
  1153. #if os(iOS)
  1154. switch self {
  1155. case .iPodTouch5: return "iPod touch (5th generation)"
  1156. case .iPodTouch6: return "iPod touch (6th generation)"
  1157. case .iPodTouch7: return "iPod touch (7th generation)"
  1158. case .iPhone4: return "iPhone 4"
  1159. case .iPhone4s: return "iPhone 4s"
  1160. case .iPhone5: return "iPhone 5"
  1161. case .iPhone5c: return "iPhone 5c"
  1162. case .iPhone5s: return "iPhone 5s"
  1163. case .iPhone6: return "iPhone 6"
  1164. case .iPhone6Plus: return "iPhone 6 Plus"
  1165. case .iPhone6s: return "iPhone 6s"
  1166. case .iPhone6sPlus: return "iPhone 6s Plus"
  1167. case .iPhone7: return "iPhone 7"
  1168. case .iPhone7Plus: return "iPhone 7 Plus"
  1169. case .iPhoneSE: return "iPhone SE"
  1170. case .iPhone8: return "iPhone 8"
  1171. case .iPhone8Plus: return "iPhone 8 Plus"
  1172. case .iPhoneX: return "iPhone X"
  1173. case .iPhoneXS: return "iPhone XS"
  1174. case .iPhoneXSMax: return "iPhone XS Max"
  1175. case .iPhoneXR: return "iPhone XR"
  1176. case .iPhone11: return "iPhone 11"
  1177. case .iPhone11Pro: return "iPhone 11 Pro"
  1178. case .iPhone11ProMax: return "iPhone 11 Pro Max"
  1179. case .iPhoneSE2: return "iPhone SE (2nd generation)"
  1180. case .iPhone12: return "iPhone 12"
  1181. case .iPhone12Mini: return "iPhone 12 mini"
  1182. case .iPhone12Pro: return "iPhone 12 Pro"
  1183. case .iPhone12ProMax: return "iPhone 12 Pro Max"
  1184. case .iPad2: return "iPad 2"
  1185. case .iPad3: return "iPad (3rd generation)"
  1186. case .iPad4: return "iPad (4th generation)"
  1187. case .iPadAir: return "iPad Air"
  1188. case .iPadAir2: return "iPad Air 2"
  1189. case .iPad5: return "iPad (5th generation)"
  1190. case .iPad6: return "iPad (6th generation)"
  1191. case .iPadAir3: return "iPad Air (3rd generation)"
  1192. case .iPad7: return "iPad (7th generation)"
  1193. case .iPad8: return "iPad (8th generation)"
  1194. case .iPadAir4: return "iPad Air (4th generation)"
  1195. case .iPadMini: return "iPad Mini"
  1196. case .iPadMini2: return "iPad Mini 2"
  1197. case .iPadMini3: return "iPad Mini 3"
  1198. case .iPadMini4: return "iPad Mini 4"
  1199. case .iPadMini5: return "iPad Mini (5th generation)"
  1200. case .iPadPro9Inch: return "iPad Pro (9.7-inch)"
  1201. case .iPadPro12Inch: return "iPad Pro (12.9-inch)"
  1202. case .iPadPro12Inch2: return "iPad Pro (12.9-inch) (2nd generation)"
  1203. case .iPadPro10Inch: return "iPad Pro (10.5-inch)"
  1204. case .iPadPro11Inch: return "iPad Pro (11-inch)"
  1205. case .iPadPro12Inch3: return "iPad Pro (12.9-inch) (3rd generation)"
  1206. case .iPadPro11Inch2: return "iPad Pro (11-inch) (2nd generation)"
  1207. case .iPadPro12Inch4: return "iPad Pro (12.9-inch) (4th generation)"
  1208. case .iPadPro11Inch3: return "iPad Pro (11-inch) (3rd generation)"
  1209. case .iPadPro12Inch5: return "iPad Pro (12.9-inch) (5th generation)"
  1210. case .homePod: return "HomePod"
  1211. case .simulator(let model): return "Simulator (\(model.safeDescription))"
  1212. case .unknown(let identifier): return identifier
  1213. }
  1214. #elseif os(watchOS)
  1215. switch self {
  1216. case .appleWatchSeries0_38mm: return "Apple Watch (1st generation) 38mm"
  1217. case .appleWatchSeries0_42mm: return "Apple Watch (1st generation) 42mm"
  1218. case .appleWatchSeries1_38mm: return "Apple Watch Series 1 38mm"
  1219. case .appleWatchSeries1_42mm: return "Apple Watch Series 1 42mm"
  1220. case .appleWatchSeries2_38mm: return "Apple Watch Series 2 38mm"
  1221. case .appleWatchSeries2_42mm: return "Apple Watch Series 2 42mm"
  1222. case .appleWatchSeries3_38mm: return "Apple Watch Series 3 38mm"
  1223. case .appleWatchSeries3_42mm: return "Apple Watch Series 3 42mm"
  1224. case .appleWatchSeries4_40mm: return "Apple Watch Series 4 40mm"
  1225. case .appleWatchSeries4_44mm: return "Apple Watch Series 4 44mm"
  1226. case .appleWatchSeries5_40mm: return "Apple Watch Series 5 40mm"
  1227. case .appleWatchSeries5_44mm: return "Apple Watch Series 5 44mm"
  1228. case .appleWatchSeries6_40mm: return "Apple Watch Series 6 40mm"
  1229. case .appleWatchSeries6_44mm: return "Apple Watch Series 6 44mm"
  1230. case .appleWatchSE_40mm: return "Apple Watch SE 40mm"
  1231. case .appleWatchSE_44mm: return "Apple Watch SE 44mm"
  1232. case .simulator(let model): return "Simulator (\(model.safeDescription))"
  1233. case .unknown(let identifier): return identifier
  1234. }
  1235. #elseif os(tvOS)
  1236. switch self {
  1237. case .appleTVHD: return "Apple TV HD"
  1238. case .appleTV4K: return "Apple TV 4K"
  1239. case .appleTV4K2: return "Apple TV 4K (2nd generation)"
  1240. case .simulator(let model): return "Simulator (\(model.safeDescription))"
  1241. case .unknown(let identifier): return identifier
  1242. }
  1243. #endif
  1244. }
  1245. }
  1246. // MARK: Equatable
  1247. extension Device: Equatable {
  1248. /// Compares two devices
  1249. ///
  1250. /// - parameter lhs: A device.
  1251. /// - parameter rhs: Another device.
  1252. ///
  1253. /// - returns: `true` iff the underlying identifier is the same.
  1254. public static func == (lhs: Device, rhs: Device) -> Bool {
  1255. return lhs.description == rhs.description
  1256. }
  1257. }
  1258. // MARK: Battery
  1259. #if os(iOS) || os(watchOS)
  1260. @available(iOS 8.0, watchOS 4.0, *)
  1261. extension Device {
  1262. /**
  1263. This enum describes the state of the battery.
  1264. - Full: The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
  1265. - Charging: The device is plugged into power and the battery is less than 100% charged.
  1266. - Unplugged: The device is not plugged into power; the battery is discharging.
  1267. */
  1268. public enum BatteryState: CustomStringConvertible, Equatable {
  1269. /// The device is plugged into power and the battery is 100% charged or the device is the iOS Simulator.
  1270. case full
  1271. /// The device is plugged into power and the battery is less than 100% charged.
  1272. /// The associated value is in percent (0-100).
  1273. case charging(Int)
  1274. /// The device is not plugged into power; the battery is discharging.
  1275. /// The associated value is in percent (0-100).
  1276. case unplugged(Int)
  1277. #if os(iOS)
  1278. fileprivate init() {
  1279. let wasBatteryMonitoringEnabled = UIDevice.current.isBatteryMonitoringEnabled
  1280. UIDevice.current.isBatteryMonitoringEnabled = true
  1281. 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
  1282. // but maybe that changes in the future.
  1283. switch UIDevice.current.batteryState {
  1284. case .charging: self = .charging(batteryLevel)
  1285. case .full: self = .full
  1286. case .unplugged: self = .unplugged(batteryLevel)
  1287. case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
  1288. @unknown default:
  1289. self = .full // To cover any future additions for which DeviceKit might not have updated yet.
  1290. }
  1291. UIDevice.current.isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
  1292. }
  1293. #elseif os(watchOS)
  1294. fileprivate init() {
  1295. let wasBatteryMonitoringEnabled = WKInterfaceDevice.current().isBatteryMonitoringEnabled
  1296. WKInterfaceDevice.current().isBatteryMonitoringEnabled = true
  1297. 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
  1298. // but maybe that changes in the future.
  1299. switch WKInterfaceDevice.current().batteryState {
  1300. case .charging: self = .charging(batteryLevel)
  1301. case .full: self = .full
  1302. case .unplugged: self = .unplugged(batteryLevel)
  1303. case .unknown: self = .full // Should never happen since `batteryMonitoring` is enabled.
  1304. @unknown default:
  1305. self = .full // To cover any future additions for which DeviceKit might not have updated yet.
  1306. }
  1307. WKInterfaceDevice.current().isBatteryMonitoringEnabled = wasBatteryMonitoringEnabled
  1308. }
  1309. #endif
  1310. /// The user enabled Low Power mode
  1311. public var lowPowerMode: Bool {
  1312. return ProcessInfo.processInfo.isLowPowerModeEnabled
  1313. }
  1314. /// Provides a textual representation of the battery state.
  1315. /// Examples:
  1316. /// ```
  1317. /// Battery level: 90%, device is plugged in.
  1318. /// Battery level: 100 % (Full), device is plugged in.
  1319. /// Battery level: \(batteryLevel)%, device is unplugged.
  1320. /// ```
  1321. public var description: String {
  1322. switch self {
  1323. case .charging(let batteryLevel): return "Battery level: \(batteryLevel)%, device is plugged in."
  1324. case .full: return "Battery level: 100 % (Full), device is plugged in."
  1325. case .unplugged(let batteryLevel): return "Battery level: \(batteryLevel)%, device is unplugged."
  1326. }
  1327. }
  1328. }
  1329. /// The state of the battery
  1330. public var batteryState: BatteryState? {
  1331. guard isCurrent else { return nil }
  1332. return BatteryState()
  1333. }
  1334. /// Battery level ranges from 0 (fully discharged) to 100 (100% charged).
  1335. public var batteryLevel: Int? {
  1336. guard isCurrent else { return nil }
  1337. switch BatteryState() {
  1338. case .charging(let value): return value
  1339. case .full: return 100
  1340. case .unplugged(let value): return value
  1341. }
  1342. }
  1343. }
  1344. #endif
  1345. // MARK: Device.Batterystate: Comparable
  1346. #if os(iOS) || os(watchOS)
  1347. @available(iOS 8.0, watchOS 4.0, *)
  1348. extension Device.BatteryState: Comparable {
  1349. /// Tells if two battery states are equal.
  1350. ///
  1351. /// - parameter lhs: A battery state.
  1352. /// - parameter rhs: Another battery state.
  1353. ///
  1354. /// - returns: `true` iff they are equal, otherwise `false`
  1355. public static func == (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
  1356. return lhs.description == rhs.description
  1357. }
  1358. /// Compares two battery states.
  1359. ///
  1360. /// - parameter lhs: A battery state.
  1361. /// - parameter rhs: Another battery state.
  1362. ///
  1363. /// - returns: `true` if rhs is `.Full`, `false` when lhs is `.Full` otherwise their battery level is compared.
  1364. public static func < (lhs: Device.BatteryState, rhs: Device.BatteryState) -> Bool {
  1365. switch (lhs, rhs) {
  1366. case (.full, _): return false // return false (even if both are `.Full` -> they are equal)
  1367. case (_, .full): return true // lhs is *not* `.Full`, rhs is
  1368. case let (.charging(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
  1369. case let (.charging(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
  1370. case let (.unplugged(lhsLevel), .charging(rhsLevel)): return lhsLevel < rhsLevel
  1371. case let (.unplugged(lhsLevel), .unplugged(rhsLevel)): return lhsLevel < rhsLevel
  1372. default: return false // compiler won't compile without it, though it cannot happen
  1373. }
  1374. }
  1375. }
  1376. #endif
  1377. #if os(iOS)
  1378. extension Device {
  1379. // MARK: Orientation
  1380. /**
  1381. This enum describes the state of the orientation.
  1382. - Landscape: The device is in Landscape Orientation
  1383. - Portrait: The device is in Portrait Orientation
  1384. */
  1385. public enum Orientation {
  1386. case landscape
  1387. case portrait
  1388. }
  1389. public var orientation: Orientation {
  1390. if UIDevice.current.orientation.isLandscape {
  1391. return .landscape
  1392. } else {
  1393. return .portrait
  1394. }
  1395. }
  1396. }
  1397. #endif
  1398. #if os(iOS)
  1399. // MARK: DiskSpace
  1400. extension Device {
  1401. /// Return the root url
  1402. ///
  1403. /// - returns: the NSHomeDirectory() url
  1404. private static let rootURL = URL(fileURLWithPath: NSHomeDirectory())
  1405. /// The volume’s total capacity in bytes.
  1406. public static var volumeTotalCapacity: Int? {
  1407. return (try? Device.rootURL.resourceValues(forKeys: [.volumeTotalCapacityKey]))?.volumeTotalCapacity
  1408. }
  1409. /// The volume’s available capacity in bytes.
  1410. public static var volumeAvailableCapacity: Int? {
  1411. return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityKey]))?.volumeAvailableCapacity
  1412. }
  1413. /// The volume’s available capacity in bytes for storing important resources.
  1414. @available(iOS 11.0, *)
  1415. public static var volumeAvailableCapacityForImportantUsage: Int64? {
  1416. return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]))?.volumeAvailableCapacityForImportantUsage
  1417. }
  1418. /// The volume’s available capacity in bytes for storing nonessential resources.
  1419. @available(iOS 11.0, *)
  1420. public static var volumeAvailableCapacityForOpportunisticUsage: Int64? { //swiftlint:disable:this identifier_name
  1421. return (try? rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForOpportunisticUsageKey]))?.volumeAvailableCapacityForOpportunisticUsage
  1422. }
  1423. /// All volumes capacity information in bytes.
  1424. @available(iOS 11.0, *)
  1425. public static var volumes: [URLResourceKey: Int64]? {
  1426. do {
  1427. let values = try rootURL.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey,
  1428. .volumeAvailableCapacityKey,
  1429. .volumeAvailableCapacityForOpportunisticUsageKey,
  1430. .volumeTotalCapacityKey
  1431. ])
  1432. return values.allValues.mapValues {
  1433. if let int = $0 as? Int64 {
  1434. return int
  1435. }
  1436. if let int = $0 as? Int {
  1437. return Int64(int)
  1438. }
  1439. return 0
  1440. }
  1441. } catch {
  1442. return nil
  1443. }
  1444. }
  1445. }
  1446. #endif
  1447. #if os(iOS)
  1448. // MARK: Apple Pencil
  1449. extension Device {
  1450. /**
  1451. This option set describes the current Apple Pencils
  1452. - firstGeneration: 1st Generation Apple Pencil
  1453. - secondGeneration: 2nd Generation Apple Pencil
  1454. */
  1455. public struct ApplePencilSupport: OptionSet {
  1456. public var rawValue: UInt
  1457. public init(rawValue: UInt) {
  1458. self.rawValue = rawValue
  1459. }
  1460. public static let firstGeneration = ApplePencilSupport(rawValue: 0x01)
  1461. public static let secondGeneration = ApplePencilSupport(rawValue: 0x02)
  1462. }
  1463. /// All Apple Pencil Capable Devices
  1464. public static var allApplePencilCapableDevices: [Device] {
  1465. return [.iPad6, .iPadAir3, .iPad7, .iPad8, .iPadAir4, .iPadMini5, .iPadPro9Inch, .iPadPro12Inch, .iPadPro12Inch2, .iPadPro10Inch, .iPadPro11Inch, .iPadPro12Inch3, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  1466. }
  1467. /// Returns supported version of the Apple Pencil
  1468. public var applePencilSupport: ApplePencilSupport {
  1469. switch self {
  1470. case .iPad6: return .firstGeneration
  1471. case .iPadAir3: return .firstGeneration
  1472. case .iPad7: return .firstGeneration
  1473. case .iPad8: return .firstGeneration
  1474. case .iPadMini5: return .firstGeneration
  1475. case .iPadPro9Inch: return .firstGeneration
  1476. case .iPadPro12Inch: return .firstGeneration
  1477. case .iPadPro12Inch2: return .firstGeneration
  1478. case .iPadPro10Inch: return .firstGeneration
  1479. case .iPadAir4: return .secondGeneration
  1480. case .iPadPro11Inch: return .secondGeneration
  1481. case .iPadPro12Inch3: return .secondGeneration
  1482. case .iPadPro11Inch2: return .secondGeneration
  1483. case .iPadPro12Inch4: return .secondGeneration
  1484. case .iPadPro11Inch3: return .secondGeneration
  1485. case .iPadPro12Inch5: return .secondGeneration
  1486. case .simulator(let model): return model.applePencilSupport
  1487. default: return []
  1488. }
  1489. }
  1490. }
  1491. #endif
  1492. #if os(iOS)
  1493. // MARK: Cameras
  1494. extension Device {
  1495. public enum CameraType {
  1496. @available(*, deprecated, renamed: "wide")
  1497. case normal
  1498. case wide
  1499. case telephoto
  1500. case ultraWide
  1501. }
  1502. /// Returns an array of the types of cameras the device has
  1503. public var cameras: [CameraType] {
  1504. switch self {
  1505. case .iPodTouch5: return [.wide]
  1506. case .iPodTouch6: return [.wide]
  1507. case .iPodTouch7: return [.wide]
  1508. case .iPhone4: return [.wide]
  1509. case .iPhone4s: return [.wide]
  1510. case .iPhone5: return [.wide]
  1511. case .iPhone5c: return [.wide]
  1512. case .iPhone5s: return [.wide]
  1513. case .iPhone6: return [.wide]
  1514. case .iPhone6Plus: return [.wide]
  1515. case .iPhone6s: return [.wide]
  1516. case .iPhone6sPlus: return [.wide]
  1517. case .iPhone7: return [.wide]
  1518. case .iPhoneSE: return [.wide]
  1519. case .iPhone8: return [.wide]
  1520. case .iPhoneXR: return [.wide]
  1521. case .iPhoneSE2: return [.wide]
  1522. case .iPad2: return [.wide]
  1523. case .iPad3: return [.wide]
  1524. case .iPad4: return [.wide]
  1525. case .iPadAir: return [.wide]
  1526. case .iPadAir2: return [.wide]
  1527. case .iPad5: return [.wide]
  1528. case .iPad6: return [.wide]
  1529. case .iPadAir3: return [.wide]
  1530. case .iPad7: return [.wide]
  1531. case .iPad8: return [.wide]
  1532. case .iPadAir4: return [.wide]
  1533. case .iPadMini: return [.wide]
  1534. case .iPadMini2: return [.wide]
  1535. case .iPadMini3: return [.wide]
  1536. case .iPadMini4: return [.wide]
  1537. case .iPadMini5: return [.wide]
  1538. case .iPadPro9Inch: return [.wide]
  1539. case .iPadPro12Inch: return [.wide]
  1540. case .iPadPro12Inch2: return [.wide]
  1541. case .iPadPro10Inch: return [.wide]
  1542. case .iPadPro11Inch: return [.wide]
  1543. case .iPadPro12Inch3: return [.wide]
  1544. case .iPhone7Plus: return [.wide, .telephoto]
  1545. case .iPhone8Plus: return [.wide, .telephoto]
  1546. case .iPhoneX: return [.wide, .telephoto]
  1547. case .iPhoneXS: return [.wide, .telephoto]
  1548. case .iPhoneXSMax: return [.wide, .telephoto]
  1549. case .iPhone11: return [.wide, .ultraWide]
  1550. case .iPhone12: return [.wide, .ultraWide]
  1551. case .iPhone12Mini: return [.wide, .ultraWide]
  1552. case .iPadPro11Inch2: return [.wide, .ultraWide]
  1553. case .iPadPro12Inch4: return [.wide, .ultraWide]
  1554. case .iPadPro11Inch3: return [.wide, .ultraWide]
  1555. case .iPadPro12Inch5: return [.wide, .ultraWide]
  1556. case .iPhone11Pro: return [.wide, .telephoto, .ultraWide]
  1557. case .iPhone11ProMax: return [.wide, .telephoto, .ultraWide]
  1558. case .iPhone12Pro: return [.wide, .telephoto, .ultraWide]
  1559. case .iPhone12ProMax: return [.wide, .telephoto, .ultraWide]
  1560. default: return []
  1561. }
  1562. }
  1563. /// All devices that feature a camera
  1564. public static var allDevicesWithCamera: [Device] {
  1565. 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]
  1566. }
  1567. /// All devices that feature a normal camera
  1568. @available(*, deprecated, renamed: "allDevicesWithWideCamera")
  1569. public static var allDevicesWithNormalCamera: [Device] {
  1570. return Device.allDevicesWithWideCamera
  1571. }
  1572. /// All devices that feature a wide camera
  1573. public static var allDevicesWithWideCamera: [Device] {
  1574. 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]
  1575. }
  1576. /// All devices that feature a telephoto camera
  1577. public static var allDevicesWithTelephotoCamera: [Device] {
  1578. return [.iPhone7Plus, .iPhone8Plus, .iPhoneX, .iPhoneXS, .iPhoneXSMax, .iPhone11Pro, .iPhone11ProMax, .iPhone12Pro, .iPhone12ProMax]
  1579. }
  1580. /// All devices that feature an ultra wide camera
  1581. public static var allDevicesWithUltraWideCamera: [Device] {
  1582. return [.iPhone11, .iPhone11Pro, .iPhone11ProMax, .iPhone12, .iPhone12Mini, .iPhone12Pro, .iPhone12ProMax, .iPadPro11Inch2, .iPadPro12Inch4, .iPadPro11Inch3, .iPadPro12Inch5]
  1583. }
  1584. /// Returns whether or not the current device has a camera
  1585. public var hasCamera: Bool {
  1586. return !self.cameras.isEmpty
  1587. }
  1588. /// Returns whether or not the current device has a normal camera
  1589. @available(*, deprecated, renamed: "hasWideCamera")
  1590. public var hasNormalCamera: Bool {
  1591. return self.hasWideCamera
  1592. }
  1593. /// Returns whether or not the current device has a wide camera
  1594. public var hasWideCamera: Bool {
  1595. return self.cameras.contains(.wide)
  1596. }
  1597. /// Returns whether or not the current device has a telephoto camera
  1598. public var hasTelephotoCamera: Bool {
  1599. return self.cameras.contains(.telephoto)
  1600. }
  1601. /// Returns whether or not the current device has an ultra wide camera
  1602. public var hasUltraWideCamera: Bool {
  1603. return self.cameras.contains(.ultraWide)
  1604. }
  1605. }
  1606. #endif