Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple Watch devices support #88

Merged
merged 6 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ jobs:
DEVELOPER_DIR: /Applications/Xcode_14.0.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Test
- name: Test (iOS)
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "UIDeviceComplete.xcodeproj" -scheme "UIDeviceComplete" -destination "OS=16.0,name=iPhone 14 Pro" clean test | xcpretty
- name: Test (watchOS)
run: set -o pipefail && env NSUnbufferedIO=YES xcodebuild -project "UIDeviceComplete.xcodeproj" -scheme "UIDeviceComplete" -destination "OS=9.0,name=Apple Watch Series 8 (45mm)" clean test | xcpretty
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import PackageDescription
let package = Package(
name: "UIDeviceComplete",
platforms: [
.iOS(.v11)
.iOS(.v11), .watchOS(.v4)
],
products: [
.library(name: "UIDeviceComplete", targets: ["UIDeviceComplete"])
Expand Down
3 changes: 3 additions & 0 deletions Sources/DeviceFamily.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public enum DeviceFamily: String {
case iPhone
case iPod
case iPad
case watch
case unknown

public init(rawValue: String) {
Expand All @@ -36,6 +37,8 @@ public enum DeviceFamily: String {
self = .iPod
case "iPad":
self = .iPad
case "Watch":
self = .watch
default:
self = .unknown
}
Expand Down
66 changes: 62 additions & 4 deletions Sources/DeviceModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

public enum DeviceModel: CaseIterable {

#if os(iOS)
case iPhone4, iPhone4S
case iPhone5, iPhone5C, iPhone5S
case iPhone6, iPhone6Plus
Expand Down Expand Up @@ -62,7 +63,24 @@ public enum DeviceModel: CaseIterable {

case iPodTouchFirstGen, iPodTouchSecondGen, iPodTouchThirdGen,
iPodTouchFourthGen, iPodTouchFifthGen, iPodTouchSixthGen, iPodTouchSeventhGen


#elseif os(watchOS)
case firstGen
case series1
case series2
case series3
case series4
case series5
case se
case series6
case series7
case series8
case se2
case ultra
case series9
case ultra2
#endif

case unknown
}

Expand All @@ -72,19 +90,24 @@ public enum DeviceModel: CaseIterable {
extension DeviceModel {
init(identifier: Identifier) {
switch identifier.type {
#if os(iOS)
case .iPhone:
self = DeviceModel.detectIphoneModel(with: identifier)
case .iPad:
self = DeviceModel.detectIpadModel(with: identifier)
case .iPod:
self = DeviceModel.detectIpodModel(with: identifier)
#elseif os(watchOS)
case .watch:
self = DeviceModel.detectWatchModel(with: identifier)
#endif
default:
self = .unknown
}
}
}


#if os(iOS)
// MARK: Detecting iPhone Models

extension DeviceModel {
Expand Down Expand Up @@ -154,8 +177,9 @@ extension DeviceModel {
}
}
}
#endif


#if os(iOS)
// MARK: Detecting iPad Models

extension DeviceModel {
Expand Down Expand Up @@ -207,8 +231,9 @@ extension DeviceModel {
}
}
}
#endif


#if os(iOS)
// MARK: Detecting iPod Models

extension DeviceModel {
Expand All @@ -230,8 +255,40 @@ extension DeviceModel {
}
}
}
#endif

#if os(watchOS)
// MARK: Detecting Apple Watch Models

extension DeviceModel {
fileprivate static func detectWatchModel(with identifier: Identifier) -> DeviceModel {
guard let major = identifier.version.major,
let minor = identifier.version.minor
else { return .unknown }

switch (major, minor) {
case (1, _): return .firstGen
case (2, 3), (2, 4): return .series2
case (2, 6), (2, 7): return .series1
case (3, _): return .series3
case (4, _): return .series4
case (5, 1), (5, 2), (5, 3), (5, 4): return .series5
case (5, 9), (5, 10), (5, 11), (5, 12): return .se
case (6, 1), (6, 2), (6, 3), (6, 4): return .series6
case (6, 6), (6, 7), (6, 8), (6, 9): return .series7
case (6, 10), (6, 11), (6, 12), (6, 13): return .se2
case (6, 14), (6, 15), (6, 16), (6, 17): return .series8
case (6, 18): return .ultra
case (7, 1), (7, 2), (7, 3), (7, 4): return .series9
case (7, 5): return .ultra2

default: return .unknown
}
}
}
#endif

#if os(iOS)
// MARK: Detecting the Notch

extension DeviceModel {
Expand Down Expand Up @@ -266,3 +323,4 @@ extension DeviceModel {
}
}
}
#endif
97 changes: 97 additions & 0 deletions Sources/Identifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ extension Identifier: CustomStringConvertible {
return iPadStringRepresentation(major: major, minor: minor)
case .iPod:
return iPodStringRepresentation(major: major, minor: minor)
case .watch:
return watchStringRepresentable(major: major, minor: minor)
case .unknown:
return "unknown"
}
Expand Down Expand Up @@ -384,4 +386,99 @@ extension Identifier: CustomStringConvertible {
return "unknown"
}
}

private func watchStringRepresentable(major: Int, minor: Int) -> String {
switch (major, minor) {
case (1, 1):
return "Apple Watch (1st generation), 38mm case"
case (1, 2):
return "Apple Watch (1st generation), 42mm case"
case (2, 3):
return "Apple Watch Series 2, 38mm case"
case (2, 4):
return "Apple Watch Series 2, 42mm case"
case (2, 6):
return "Apple Watch Series 1, 38mm case"
case (2, 7):
return "Apple Watch Series 1, 42mm case"
case (3, 1):
return "Apple Watch Series 3, 38mm case (GPS + Cellular)"
case (3, 2):
return "Apple Watch Series 3, 42mm case (GPS + Cellular)"
case (3, 3):
return "Apple Watch Series 3, 38mm case (GPS)"
case (3, 4):
return "Apple Watch Series 3, 42mm case (GPS)"
case (4, 1):
return "Apple Watch Series 4, 40mm case (GPS)"
case (4, 2):
return "Apple Watch Series 4, 44mm case (GPS)"
case (4, 3):
return "Apple Watch Series 4, 40mm case (GPS + Cellular)"
case (4, 4):
return "Apple Watch Series 4, 44mm case (GPS + Cellular)"
case (5, 1):
return "Apple Watch Series 5, 40mm case (GPS)"
case (5, 2):
return "Apple Watch Series 5, 44mm case (GPS)"
case (5, 3):
return "Apple Watch Series 5, 40mm case (GPS + Cellular)"
case (5, 4):
return "Apple Watch Series 5, 44mm case (GPS + Cellular)"
case (5, 9):
return "Apple Watch SE, 40mm case (GPS)"
case (5, 10):
return "Apple Watch SE, 44mm case (GPS)"
case (5, 11):
return "Apple Watch SE, 40mm case (GPS + Cellular)"
case (5, 12):
return "Apple Watch SE, 44mm case (GPS + Cellular)"
case (6, 1):
return "Apple Watch Series 6, 40mm case (GPS)"
case (6, 2):
return "Apple Watch Series 6, 44mm case (GPS)"
case (6, 3):
return "Apple Watch Series 6, 40mm case (GPS + Cellular)"
case (6, 4):
return "Apple Watch Series 6, 44mm case (GPS + Cellular)"
case (6, 6):
return "Apple Watch Series 7, 41mm case (GPS)"
case (6, 7):
return "Apple Watch Series 7, 45mm case (GPS)"
case (6, 8):
return "Apple Watch Series 7, 41mm case (GPS + Cellular)"
case (6, 9):
return "Apple Watch Series 7, 45mm case (GPS + Cellular)"
case (6, 10):
return "Apple Watch SE (2nd Generation), 40mm case (GPS)"
case (6, 11):
return "Apple Watch SE (2nd Generation), 44mm case (GPS)"
case (6, 12):
return "Apple Watch SE (2nd Generation), 40mm case (GPS + Cellular)"
case (6, 13):
return "Apple Watch SE (2nd Generation), 44mm case (GPS + Cellular)"
case (6, 14):
return "Apple Watch Series 8, 41mm case (GPS)"
case (6, 15):
return "Apple Watch Series 8, 45mm case (GPS)"
case (6, 16):
return "Apple Watch Series 8, 41mm case (GPS + Cellular)"
case (6, 17):
return "Apple Watch Series 8, 45mm case (GPS + Cellular)"
case (6, 18):
return "Apple Watch Ultra"
case (7, 1):
return "Apple Watch Series 9, 41mm case (GPS)"
case (7, 2):
return "Apple Watch Series 9, 45mm case (GPS)"
case (7, 3):
return "Apple Watch Series 9, 41mm case (GPS + Cellular)"
case (7, 4):
return "Apple Watch Series 9, 45mm case (GPS + Cellular)"
case (7, 5):
return "Apple Watch Ultra 2"
default:
return "unknown"
}
}
}
42 changes: 41 additions & 1 deletion Sources/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#if os(iOS)
import UIKit
#endif

public struct Screen {
#if os(iOS)
init(width: Double, height: Double, scale: Double) {
self.width = width
self.height = height
Expand All @@ -37,9 +40,16 @@ public struct Screen {
public var adjustedScale: Double {
return 1.0 / scale
}
#elseif os(watchOS)
init(identifier: Identifier) {
self.identifier = identifier
}

let identifier: Identifier
#endif
}


#if os(iOS)
// MARK: - Detecting Screen size in Inches

extension Screen {
Expand Down Expand Up @@ -89,3 +99,33 @@ extension Screen {
}

}
#endif

#if os(watchOS)
extension Screen {
public var caseSize: Int? {
guard let major = identifier.version.major,
let minor = identifier.version.minor
else { return nil }

switch (major, minor) {
case (1, 1), (2, 3), (2, 6), (3, 1), (3, 3): return 38
case (1, 2), (2, 4), (2, 7), (3, 2), (3, 4): return 42

case (4, 1), (4, 3), (5, 1), (5, 3), (5, 9),
(5, 11), (6, 1), (6, 3), (6, 10), (6, 12): return 40
case (4, 2), (4, 4), (5, 2), (5, 4), (5, 10),
(5, 12), (6, 2), (6, 4), (6, 11), (6, 13): return 44

case (6, 6), (6, 8), (6, 14), (6, 16),
(7, 1), (7, 3): return 41
case (6, 7), (6, 9), (6, 15), (6, 17),
(7, 2), (7, 4): return 45

case (6, 18), (7, 5): return 49

default: return nil
}
}
}
#endif
8 changes: 8 additions & 0 deletions Sources/UIDeviceComplete.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#if os(iOS)
import UIKit
#elseif os(watchOS)
import WatchKit
#endif

public final class UIDeviceComplete<Base> {
let base: Base
Expand All @@ -42,4 +46,8 @@ public extension UIDeviceCompleteCompatible {
}
}

#if os(iOS)
extension UIDevice: UIDeviceCompleteCompatible { }
#elseif os(watchOS)
extension WKInterfaceDevice: UIDeviceCompleteCompatible { }
#endif
Loading
Loading