diff --git a/Assets/iphone-x-screen-demystified.svg b/Assets/iphone-x-screen-demystified.svg new file mode 100644 index 0000000..4f007e9 --- /dev/null +++ b/Assets/iphone-x-screen-demystified.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 375 pt + + + + + + + 83 pt + + + + + + + 83 pt + + + + + + + 209 pt + + + + + + + 30 pt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 40 pt radius + + 6 pt radius + + 20 pt radius + + + + + + + + + + + + + + + + + + + + + + Source: https://www.paintcodeapp.com/news/iphone-x-screen-demystified + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index de39f6b..fc82781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +## [2.2.4] - 2022-16-03 +### Fixed + - Fixed incorrect layout on `NotchGradientLoadingBar` when using iPhone XR + ## [2.2.3] - 2021-29-12 ### Fixed - Fixed incorrect layout on `NotchGradientLoadingBar` when using an increased height ([#026], thanks to [alinfarcas12](https://github.com/alinfarcas12)) @@ -159,7 +163,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - Initial release -[Unreleased]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.3...master +[Unreleased]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.4...master +[2.2.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.3...2.2.4 [2.2.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.2...2.2.3 [2.2.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.1...2.2.2 [2.2.1]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.0...2.2.1 diff --git a/Example/ExampleTests/ViewModel/NotchGradientLoadingBarViewModelTestCase.swift b/Example/ExampleTests/ViewModel/NotchGradientLoadingBarViewModelTestCase.swift index 9be5c57..9c7ace7 100644 --- a/Example/ExampleTests/ViewModel/NotchGradientLoadingBarViewModelTestCase.swift +++ b/Example/ExampleTests/ViewModel/NotchGradientLoadingBarViewModelTestCase.swift @@ -13,7 +13,7 @@ import XCTest final class NotchGradientLoadingBarViewModelTestCase: XCTestCase { func test_initializer_shouldSetSafeAreaDevice_toIPhoneX() { // Given - let deviceIdentifiers = ["iPhone10,3", "iPhone10,6", "iPhone11,2", "iPhone11,4", "iPhone11,6", "iPhone11,8"] + let deviceIdentifiers = ["iPhone10,3", "iPhone10,6", "iPhone11,2", "iPhone11,4", "iPhone11,6"] deviceIdentifiers.forEach { deviceIdentifier in // When @@ -24,6 +24,19 @@ final class NotchGradientLoadingBarViewModelTestCase: XCTestCase { } } + func test_initializer_shouldSetSafeAreaDevice_toIPhoneXR() { + // Given + let deviceIdentifiers = ["iPhone11,8"] + deviceIdentifiers.forEach { deviceIdentifier in + + // When + let viewModel = NotchGradientLoadingBarViewModel(deviceIdentifier: deviceIdentifier) + + // Then + XCTAssertEqual(viewModel.safeAreaDevice, .iPhoneXR) + } + } + func test_initializer_shouldSetSafeAreaDevice_toIPhone11() { // Given let deviceIdentifiers = ["iPhone12,1", "iPhone12,3", "iPhone12,5"] diff --git a/Example/Podfile.lock b/Example/Podfile.lock index e7db2cd..07f199c 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,15 +1,15 @@ PODS: - - GradientLoadingBar (2.2.3): + - GradientLoadingBar (2.2.4): - LightweightObservable (~> 2.1) - - LightweightObservable (2.2.0) + - LightweightObservable (2.1.2) - SnapshotTesting (1.9.0) - SwiftConfigurationFiles (0.0.1) - - SwiftFormat/CLI (0.49.5) - - SwiftLint (0.46.4) + - SwiftFormat/CLI (0.49.1) + - SwiftLint (0.45.1) DEPENDENCIES: - GradientLoadingBar (from `../`) - - SnapshotTesting (~> 1.9) + - SnapshotTesting (~> 1.7) - SwiftConfigurationFiles (from `https://github.com/fxm90/SwiftConfigurationFiles.git`) - SwiftFormat/CLI (~> 0.41) - SwiftLint (~> 0.42) @@ -33,13 +33,13 @@ CHECKOUT OPTIONS: :git: https://github.com/fxm90/SwiftConfigurationFiles.git SPEC CHECKSUMS: - GradientLoadingBar: 1b12f3fc5b8ec3807cbad43c64a7ee66011789f2 - LightweightObservable: a4fce3323002aa57234f3cf5524eecb144cc781f + GradientLoadingBar: 8972571e271c2da98f84a97de08f143c66df1894 + LightweightObservable: c5ac85423a5edbed9a920b4d5c7b8f94ab3688c4 SnapshotTesting: 6141c48b6aa76ead61431ca665c14ab9a066c53b SwiftConfigurationFiles: 1cf2228a911ebed9f42f8dec077bb634f04ca6c8 - SwiftFormat: 803e5a44e083cf414b3072381db0e9e65f4c0d0d - SwiftLint: b24bab3f5ab5c9ae86a03381bc974d6f0ac85bb0 + SwiftFormat: 16b41f3229f5e7edb130ac4cd631cceed7af7d5e + SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761 -PODFILE CHECKSUM: 236416c4c4856713b28b6bf3da014054e9b319f2 +PODFILE CHECKSUM: 36b90780cb508f9eaca4f0ac59660e3e748de601 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json index 8242c0a..883b5fd 100644 --- a/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json +++ b/Example/Pods/Local Podspecs/GradientLoadingBar.podspec.json @@ -1,6 +1,6 @@ { "name": "GradientLoadingBar", - "version": "2.2.3", + "version": "2.2.4", "summary": "A customizable animated gradient loading bar.", "description": "A customizable animated gradient loading bar.\nInspired by https://codepen.io/marcobiedermann/pen/LExXWW", "homepage": "https://github.com/fxm90/GradientLoadingBar", @@ -14,7 +14,7 @@ }, "source": { "git": "https://github.com/fxm90/GradientLoadingBar.git", - "tag": "2.2.3" + "tag": "2.2.4" }, "swift_versions": "5.5", "platforms": { diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index e7db2cd..07f199c 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,15 +1,15 @@ PODS: - - GradientLoadingBar (2.2.3): + - GradientLoadingBar (2.2.4): - LightweightObservable (~> 2.1) - - LightweightObservable (2.2.0) + - LightweightObservable (2.1.2) - SnapshotTesting (1.9.0) - SwiftConfigurationFiles (0.0.1) - - SwiftFormat/CLI (0.49.5) - - SwiftLint (0.46.4) + - SwiftFormat/CLI (0.49.1) + - SwiftLint (0.45.1) DEPENDENCIES: - GradientLoadingBar (from `../`) - - SnapshotTesting (~> 1.9) + - SnapshotTesting (~> 1.7) - SwiftConfigurationFiles (from `https://github.com/fxm90/SwiftConfigurationFiles.git`) - SwiftFormat/CLI (~> 0.41) - SwiftLint (~> 0.42) @@ -33,13 +33,13 @@ CHECKOUT OPTIONS: :git: https://github.com/fxm90/SwiftConfigurationFiles.git SPEC CHECKSUMS: - GradientLoadingBar: 1b12f3fc5b8ec3807cbad43c64a7ee66011789f2 - LightweightObservable: a4fce3323002aa57234f3cf5524eecb144cc781f + GradientLoadingBar: 8972571e271c2da98f84a97de08f143c66df1894 + LightweightObservable: c5ac85423a5edbed9a920b4d5c7b8f94ab3688c4 SnapshotTesting: 6141c48b6aa76ead61431ca665c14ab9a066c53b SwiftConfigurationFiles: 1cf2228a911ebed9f42f8dec077bb634f04ca6c8 - SwiftFormat: 803e5a44e083cf414b3072381db0e9e65f4c0d0d - SwiftLint: b24bab3f5ab5c9ae86a03381bc974d6f0ac85bb0 + SwiftFormat: 16b41f3229f5e7edb130ac4cd631cceed7af7d5e + SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761 -PODFILE CHECKSUM: 236416c4c4856713b28b6bf3da014054e9b319f2 +PODFILE CHECKSUM: 36b90780cb508f9eaca4f0ac59660e3e748de601 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar-Info.plist b/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar-Info.plist index 086f7e6..bb11c61 100644 --- a/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar-Info.plist +++ b/Example/Pods/Target Support Files/GradientLoadingBar/GradientLoadingBar-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.2.3 + 2.2.4 CFBundleSignature ???? CFBundleVersion diff --git a/GradientLoadingBar.podspec b/GradientLoadingBar.podspec index 0c53ba8..c85b504 100644 --- a/GradientLoadingBar.podspec +++ b/GradientLoadingBar.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'GradientLoadingBar' - s.version = '2.2.3' + s.version = '2.2.4' s.summary = 'A customizable animated gradient loading bar.' # This description is used to generate tags and improve search results. diff --git a/GradientLoadingBar/NotchGradientLoadingBarController.swift b/GradientLoadingBar/NotchGradientLoadingBarController.swift index f404c40..5ede9ed 100644 --- a/GradientLoadingBar/NotchGradientLoadingBarController.swift +++ b/GradientLoadingBar/NotchGradientLoadingBarController.swift @@ -8,51 +8,34 @@ import UIKit +// MARK: - Types + +private struct NotchConfig { + /// The width of the iPhone notch. + let notchWidth: CGFloat + + /// The radius of the small circle on the outside of the notch. + let smallCircleRadius: CGFloat = 6 + + /// The radius of the large circle on the inside of the notch. + let largeCircleRadius: CGFloat + + /// Offset for the center-point of the large circle. + /// + /// - A positive value for the `X` property will move the large circles closer to the center of the screen. A negative offset closer to + /// the corners of the screen. + /// + /// - A positive value for the `Y` property will move the large circles downwards. A negative offset will move them upwards. + let largeCircleOffset: CGPoint + + /// The transform to be applied to the entire bezier path. + let transform: CGAffineTransform +} + /// Type-alias for the controller to be more similar to the pod name. public typealias NotchGradientLoadingBar = NotchGradientLoadingBarController open class NotchGradientLoadingBarController: GradientLoadingBarController { - // MARK: - Config - - private struct Config { - /// The default configuration for the iPhone X and 11. - /// Values are based on . - static let `default` = Config(notchWidth: 208, - largeCircleRadius: 22.5, - verticalOffsetForLargeCircle: -4.75, - transform: CGAffineTransform(translationX: 0.33, y: 0)) - - /// The iPhone 12 specific configuration. - static let iPhone12Device = Config(notchWidth: 209.5, - largeCircleRadius: 21, - verticalOffsetForLargeCircle: -1.75, - transform: .identity) - - // The iPhone 13 specific configuration: ‟iPhone 13 notch is 20% smaller in width, but it is also a little taller in height‟. - // Source: . - static let iPhone13Device = Config(notchWidth: 161, - largeCircleRadius: 22, - verticalOffsetForLargeCircle: -1, - transform: .identity) - - /// The width of the iPhone notch. - let notchWidth: CGFloat - - /// The radius of the small circle on the outside of the notch. - let smallCircleRadius: CGFloat = 6 - - /// The radius of the large circle on the inside of the notch. - let largeCircleRadius: CGFloat - - /// We're moving the the large-circles a bit up. - /// This prevents having a straight line between the circles. - /// See - let verticalOffsetForLargeCircle: CGFloat - - /// The transform to be applied to the bezier path. - let transform: CGAffineTransform - } - // MARK: - Private properties private let viewModel = NotchGradientLoadingBarViewModel() @@ -83,19 +66,7 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { // As we currently only support portrait mode (and no device rotation), we can safely use `bounds.size.width` here. let screenWidth = superview.bounds.size.width - let config: Config - switch viewModel.safeAreaDevice { - case .unknown, .iPhoneX, .iPhone11: - config = .default - - case .iPhone12: - config = .iPhone12Device - - case .iPhone13: - config = .iPhone13Device - } - - let notchBezierPath = notchBezierPath(for: screenWidth, config: config) + let notchBezierPath = self.notchBezierPath(for: screenWidth, notchConfig: viewModel.safeAreaDevice.notchConfig) // Setting the `lineWidth` draws a line, where the actual path is exactly in the middle of the drawn line. // To get the correct height (including the path) we have to add the `height` here to the given bounds (half height for top, half for bottom). @@ -114,14 +85,15 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { // MARK: - Private methods // swiftlint:disable:next function_body_length - private func notchBezierPath(for screenWidth: CGFloat, config: Config) -> UIBezierPath { + private func notchBezierPath(for screenWidth: CGFloat, notchConfig: NotchConfig) -> UIBezierPath { // We always center the notch in the middle of the screen. - let leftNotchPoint = (screenWidth - config.notchWidth) / 2 - let rightNotchPoint = (screenWidth + config.notchWidth) / 2 + let leftNotchPoint = (screenWidth - notchConfig.notchWidth) / 2 + let rightNotchPoint = (screenWidth + notchConfig.notchWidth) / 2 // The center point of the large circles lays at the bottom of the small circles. - // See graphic https://www.paintcodeapp.com/news/iphone-x-screen-demystified for further details. - let smallCircleDiameter: CGFloat = 2 * config.smallCircleRadius + // Please have a look at the graphic `Assets/iphone-x-screen-demystified.svg` or the entire article at + // https://www.paintcodeapp.com/news/iphone-x-screen-demystified for further details on the notch layout. + let smallCircleDiameter: CGFloat = 2 * notchConfig.smallCircleRadius // Reducing the height here a little in order to match the "basic" gradient loading bar. let height = height - 0.5 @@ -130,43 +102,43 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { bezierPath.move(to: .zero) // Draw line to small-circle left to `leftNotchPoint`. - bezierPath.addLineTo(x: leftNotchPoint - config.smallCircleRadius, + bezierPath.addLineTo(x: leftNotchPoint - notchConfig.smallCircleRadius, y: 0) // Draw the small circle left to the `leftNotchPoint`. // See for the definition of the // angles in the default coordinate system. - bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint - config.smallCircleRadius, - y: config.smallCircleRadius), - radius: config.smallCircleRadius, + bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint - notchConfig.smallCircleRadius, + y: notchConfig.smallCircleRadius), + radius: notchConfig.smallCircleRadius, startAngle: -CGFloat.pi / 2, endAngle: 0, clockwise: true) // Draw the large circle right to the `leftNotchPoint`. - bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint + config.largeCircleRadius, - y: smallCircleDiameter + config.verticalOffsetForLargeCircle), - radius: config.largeCircleRadius, + bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint + notchConfig.largeCircleRadius + notchConfig.largeCircleOffset.x, + y: smallCircleDiameter + notchConfig.largeCircleOffset.y), + radius: notchConfig.largeCircleRadius, startAngle: CGFloat.pi, endAngle: CGFloat.pi / 2, clockwise: false) // Draw line to large-circle underneath and left to `rightNotchPoint`. - bezierPath.addLineTo(x: rightNotchPoint - config.largeCircleRadius, - y: smallCircleDiameter + config.largeCircleRadius + config.verticalOffsetForLargeCircle) + bezierPath.addLineTo(x: rightNotchPoint - notchConfig.largeCircleRadius - notchConfig.largeCircleOffset.x, + y: smallCircleDiameter + notchConfig.largeCircleRadius + notchConfig.largeCircleOffset.y) // Draw the large circle left to the `rightNotchPoint`. - bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint - config.largeCircleRadius, - y: smallCircleDiameter + config.verticalOffsetForLargeCircle), - radius: config.largeCircleRadius, + bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint - notchConfig.largeCircleRadius - notchConfig.largeCircleOffset.x, + y: smallCircleDiameter + notchConfig.largeCircleOffset.y), + radius: notchConfig.largeCircleRadius, startAngle: CGFloat.pi / 2, endAngle: 0, clockwise: false) // Draw the small circle right to the `rightNotchPoint`. - bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint + config.smallCircleRadius, - y: config.smallCircleRadius), - radius: config.smallCircleRadius, + bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint + notchConfig.smallCircleRadius, + y: notchConfig.smallCircleRadius), + radius: notchConfig.smallCircleRadius, startAngle: CGFloat.pi, endAngle: CGFloat.pi + CGFloat.pi / 2, clockwise: true) @@ -177,14 +149,14 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { // And all the way back.. // Have the small-circle at the bottom-path only ⅔ of the size of the upper-path produced visually better results. - let bottomPathSmallCircleRadius = (config.smallCircleRadius / 3) * 2 + let bottomPathSmallCircleRadius = (notchConfig.smallCircleRadius / 3) * 2 // Draw line down. bezierPath.addLineTo(x: screenWidth, y: height) // Draw line to small-circle underneath and right to `rightNotchPoint`. - bezierPath.addLineTo(x: rightNotchPoint + bottomPathSmallCircleRadius + height, + bezierPath.addLineTo(x: height + rightNotchPoint + bottomPathSmallCircleRadius, y: height) // Draw the small circle right to the `rightNotchPoint`. @@ -196,21 +168,30 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { clockwise: false) // Draw the large circle left to the `rightNotchPoint`. - bezierPath.addArc(withCenter: CGPoint(x: height + rightNotchPoint - config.largeCircleRadius, - y: height + smallCircleDiameter + config.verticalOffsetForLargeCircle), - radius: config.largeCircleRadius, + // + // We explicitly ignore the horizontal offset (`notchConfig.largeCircleOffset.x`) here, to have the paths of the + // small- and large-circles end/begin on the same point on the x-axis. + bezierPath.addArc(withCenter: CGPoint(x: height + rightNotchPoint - notchConfig.largeCircleRadius, + y: height + smallCircleDiameter + notchConfig.largeCircleOffset.y), + radius: notchConfig.largeCircleRadius, startAngle: 0, endAngle: CGFloat.pi / 2, clockwise: true) // Draw line to large-circle underneath and right to `leftNotchPoint` - bezierPath.addLineTo(x: height + leftNotchPoint + config.largeCircleRadius, - y: height + smallCircleDiameter + config.largeCircleRadius + config.verticalOffsetForLargeCircle) + // + // We explicitly ignore the horizontal offset (`notchConfig.largeCircleOffset.x`) here, to have the paths of the + // small- and large-circles end/begin on the same point on the x-axis. + bezierPath.addLineTo(x: height + leftNotchPoint + notchConfig.largeCircleRadius, + y: height + smallCircleDiameter + notchConfig.largeCircleRadius + notchConfig.largeCircleOffset.y) // Draw the large circle right to the `leftNotchPoint`. - bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint - height + config.largeCircleRadius, - y: height + smallCircleDiameter + config.verticalOffsetForLargeCircle), - radius: config.largeCircleRadius, + // + // We explicitly ignore the horizontal offset (`notchConfig.largeCircleOffset.x`) here, to have the paths of the + // small- and large-circles end/begin on the same point on the x-axis. + bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint - height + notchConfig.largeCircleRadius, + y: height + smallCircleDiameter + notchConfig.largeCircleOffset.y), + radius: notchConfig.largeCircleRadius, startAngle: CGFloat.pi / 2, endAngle: CGFloat.pi, clockwise: true) @@ -227,7 +208,7 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { bezierPath.addLineTo(x: 0, y: height) bezierPath.close() - bezierPath.apply(config.transform) + bezierPath.apply(notchConfig.transform) return bezierPath } @@ -247,6 +228,41 @@ open class NotchGradientLoadingBarController: GradientLoadingBarController { // MARK: - Helpers +private extension NotchGradientLoadingBarViewModel.SafeAreaDevice { + /// The notch specific configuration for the current device. + var notchConfig: NotchConfig { + switch self { + case .unknown, .iPhoneX, .iPhone11: + /// The default configuration for the iPhone X and 11. + /// Values are based on . + return NotchConfig(notchWidth: 208, + largeCircleRadius: 22.5, + largeCircleOffset: CGPoint(x: 0, y: -4.75), + transform: CGAffineTransform(translationX: 0.33, y: 0)) + + case .iPhoneXR: + return NotchConfig(notchWidth: 232, + largeCircleRadius: 24, + largeCircleOffset: CGPoint(x: 0.5, y: -3.5), + transform: .identity) + + case .iPhone12: + return NotchConfig(notchWidth: 209.5, + largeCircleRadius: 21, + largeCircleOffset: CGPoint(x: 0, y: -1.75), + transform: .identity) + + case .iPhone13: + // The iPhone 13 specific configuration: ‟iPhone 13 notch is 20% smaller in width, but it is also a little taller in height‟. + // Source: . + return NotchConfig(notchWidth: 161, + largeCircleRadius: 22, + largeCircleOffset: CGPoint(x: 0, y: -1), + transform: .identity) + } + } +} + private extension UIBezierPath { // swiftlint:disable:next identifier_name func addLineTo(x: CGFloat, y: CGFloat) { diff --git a/GradientLoadingBar/ViewModel/NotchGradientLoadingBarViewModel.swift b/GradientLoadingBar/ViewModel/NotchGradientLoadingBarViewModel.swift index 3470bbd..e35b3b9 100644 --- a/GradientLoadingBar/ViewModel/NotchGradientLoadingBarViewModel.swift +++ b/GradientLoadingBar/ViewModel/NotchGradientLoadingBarViewModel.swift @@ -14,6 +14,7 @@ final class NotchGradientLoadingBarViewModel { enum SafeAreaDevice { case unknown case iPhoneX + case iPhoneXR case iPhone11 case iPhone12 case iPhone13 @@ -39,9 +40,12 @@ private extension NotchGradientLoadingBarViewModel.SafeAreaDevice { /// Taken from init(deviceIdentifier: String) { switch deviceIdentifier { - case "iPhone10,3", "iPhone10,6", "iPhone11,2", "iPhone11,4", "iPhone11,6", "iPhone11,8": + case "iPhone10,3", "iPhone10,6", "iPhone11,2", "iPhone11,4", "iPhone11,6": self = .iPhoneX + case "iPhone11,8": + self = .iPhoneXR + case "iPhone12,1", "iPhone12,3", "iPhone12,5": self = .iPhone11