Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

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