-
Notifications
You must be signed in to change notification settings - Fork 21
/
UIScreenExtension.swift
164 lines (134 loc) · 9.9 KB
/
UIScreenExtension.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//
// UIScreenExtension.swift
// UIScreenExtension
//
// Created by Jens Schwarzer on 02/10/2017.
// Copyright © 2017 marchv. All rights reserved.
//
import UIKit
internal extension UIDevice {
// model identifiers can be found at https://www.theiphonewiki.com/wiki/Models
static let modelIdentifier: String = {
if let simulatorModelIdentifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] { return simulatorModelIdentifier }
var sysinfo = utsname()
uname(&sysinfo) // ignore return value
return String(bytes: Data(bytes: &sysinfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)!.trimmingCharacters(in: .controlCharacters)
}()
}
private func computeIfSome<T: Any, S: Any>(optional: T?, computation: ((T) -> S)) -> S? { if let some = optional { return computation(some) } else { return .none } }
@available(iOS 9.0, *)
public extension UIScreen {
/// The screen dimension in inches
static let diagonalInInches: CGFloat? = {
switch UIDevice.modelIdentifier {
case "iPhone4,1": // iPhone 4S
return 3.5
case "iPhone5,1", "iPhone5,2": fallthrough // iPhone 5
case "iPhone5,3", "iPhone5,4": fallthrough // iPhone 5C
case "iPhone6,1", "iPhone6,2": fallthrough // iPhone 5S
case "iPhone8,4": fallthrough // iPhone SE
case "iPod5,1": fallthrough // iPod Touch 5th generation
case "iPod7,1": fallthrough // iPod Touch 6th generation
case "iPod9,1": // iPod Touch 7th generation
return 4.0
case "iPhone7,2": fallthrough // iPhone 6
case "iPhone8,1": fallthrough // iPhone 6S
case "iPhone9,1", "iPhone9,3": fallthrough // iPhone 7
case "iPhone10,1", "iPhone10,4": fallthrough // iPhone 8
case "iPhone12,8": fallthrough // iPhone SE 2nd generation
case "iPhone14,6": // iPhone SE (3rd generation)
return 4.7
case "iPhone13,1": fallthrough // iPhone 12 Mini
case "iPhone14,4": // iPhone 13 Mini
return 5.4
case "iPhone7,1": fallthrough // iPhone 6 Plus
case "iPhone8,2": fallthrough // iPhone 6S Plus
case "iPhone9,2", "iPhone9,4": fallthrough // iPhone 7 Plus
case "iPhone10,2", "iPhone10,5": // iPhone 8 Plus
return 5.5
case "iPhone10,3", "iPhone10,6": fallthrough // iPhone X
case "iPhone11,2": fallthrough // iPhone XS
case "iPhone12,3": // iPhone 11 Pro
return 5.8
case "iPhone11,8": fallthrough // iPhone XR
case "iPhone12,1": fallthrough // iPhone 11
case "iPhone13,2": fallthrough // iPhone 12
case "iPhone13,3": fallthrough // iPhone 12 Pro
case "iPhone14,5": fallthrough // iPhone 13
case "iPhone14,2": fallthrough // iPhone 13 Pro
case "iPhone14,7": fallthrough // iPhone 14
case "iPhone15,2": fallthrough // iPhone 14 Pro
case "iPhone15,4": fallthrough // iPhone 15
case "iPhone16,1": // iPhone 15 Pro
return 6.1
case "iPhone11,4", "iPhone11,6": fallthrough // iPhone XS Max
case "iPhone12,5": // iPhone 11 Pro Max
return 6.5
case "iPhone13,4": fallthrough // iPhone 12 Pro Max
case "iPhone14,3": fallthrough // iPhone 13 Pro Max
case "iPhone14,8": fallthrough // iPhone 14 Plus
case "iPhone15,3": fallthrough // iPhone 14 Pro Max
case "iPhone15,5": fallthrough // iPhone 15 Plus
case "iPhone16,2": // iPhone 15 Pro Max
return 6.7
case "iPad2,5", "iPad2,6", "iPad2,7": fallthrough // iPad Mini
case "iPad4,4", "iPad4,5", "iPad4,6": fallthrough // iPad Mini 2
case "iPad4,7", "iPad4,8", "iPad4,9": fallthrough // iPad Mini 3
case "iPad5,1", "iPad5,2": fallthrough // iPad Mini 4
case "iPad11,1", "iPad11,2": fallthrough // iPad Mini 5
case "iPad14,1", "iPad14,2": // iPad Mini 6
return 7.9
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": fallthrough // iPad 2
case "iPad3,1", "iPad3,2", "iPad3,3": fallthrough // iPad 3rd generation
case "iPad3,4", "iPad3,5", "iPad3,6": fallthrough // iPad 4th generation
case "iPad4,1", "iPad4,2", "iPad4,3": fallthrough // iPad Air
case "iPad5,3", "iPad5,4": fallthrough // iPad Air 2
case "iPad6,3", "iPad6,4": fallthrough // iPad Pro (9.7 inch)
case "iPad6,11", "iPad6,12": fallthrough // iPad 5th generation
case "iPad7,5", "iPad7,6": // iPad 6th generation
return 9.7
case "iPad7,11", "iPad7,12": fallthrough // iPad 7th generation
case "iPad11,6", "iPad11,7": fallthrough // iPad 8th generation
case "iPad12,1", "iPad12,2": // iPad 9th generation
return 10.2
case "iPad7,3", "iPad7,4": fallthrough // iPad Pro (10.5 inch)
case "iPad11,3", "iPad11,4": // iPad Air (3rd generation)
return 10.5
case "iPad13,1", "iPad13,2": fallthrough // iPad Air (4th generation)
case "iPad13,18", "iPad13,19": fallthrough // iPad 10th generation
case "iPad13,16", "iPad13,17": // iPad Air (5th generation)
return 10.9
case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4": fallthrough // iPad Pro (11 inch)
case "iPad8,9", "iPad8,10": fallthrough // iPad Pro (11 inch, 2nd generation)
case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7": fallthrough // iPad Pro (11 inch, 3rd generation)
case "iPad14,3", "iPad14,4": // iPad Pro (11 inch, 4th generation)
return 11.0
case "iPad6,7", "iPad6,8": fallthrough // iPad Pro (12.9 inch)
case "iPad7,1", "iPad7,2": fallthrough // iPad Pro (12.9 inch, 2nd generation)
case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8": fallthrough // iPad Pro (12.9 inch, 3rd generation)
case "iPad8,11", "iPad8,12": fallthrough // iPad Pro (12.9 inch, 4th generation)
case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11": fallthrough // iPad Pro (12.9 inch, 5th generation)
case "iPad14,5", "iPad14,6": // iPad Pro (12.9 inch, 6th generation)
return 12.9
default: // unknown model identifier
return .none
}
}()
/// The number of pixels per inch for this device
static let pixelsPerInch: CGFloat? = computeIfSome(optional: dimensionInInches, computation: { main.nativeBounds.height / $0.height })
/// The number of pixels per centimeter for this device
static let pixelsPerCentimeter: CGFloat? = computeIfSome(optional: pixelsPerInch, computation: { $0 / 2.54 })
/// The number of points per inch for this device
static let pointsPerInch: CGFloat? = computeIfSome(optional: pixelsPerInch, computation: { $0 / main.nativeScale })
/// The number of points per centimeter for this device
static let pointsPerCentimeter: CGFloat? = computeIfSome(optional: pixelsPerCentimeter, computation: { $0 / main.nativeScale })
/// The screen dimension in inches
static let dimensionInInches: CGSize? = computeIfSome(optional: diagonalInInches, computation: {
let ratio = main.nativeBounds.width / main.nativeBounds.height
let height = $0 / sqrt(pow(ratio, 2) + 1)
let width = ratio * height
return CGSize(width: width, height: height)
})
/// The screen dimension in centimeters
static let dimensionInCentimeters: CGSize? = computeIfSome(optional: pixelsPerCentimeter, computation: { CGSize(width: main.nativeBounds.width / $0, height: main.nativeBounds.height / $0) })
}