Skip to content
Open
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
Empty file added .context/notes.md
Empty file.
Empty file added .context/todos.md
Empty file.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
- platform=tvOS Simulator,name=Apple TV
- platform=tvOS Simulator,name=Apple TV 4K (3rd generation)
- platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)
- platform=visionOS Simulator,name=Apple Vision Pro

steps:
- uses: actions/checkout@v4
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Add support for M5 iPad Pro models. ([#467](https://github.com/devicekit/DeviceKit/pull/467))
- Add support for Apple Watch SE (3rd generation) ([#473](https://github.com/devicekit/DeviceKit/pull/473))
- Add support for iPhone 17e and iPad Air (M4)
- Add support for Apple Vision Pro and Apple Vision Pro (M5)

| Device | Case value |
| --- | --- |
Expand All @@ -17,6 +18,8 @@
| iPhone 17e | `Device.iPhone17e` |
| iPad Air (11-inch) (M4) | `Device.iPadAir11M4` |
| iPad Air (13-inch) (M4) | `Device.iPadAir13M4` |
| Apple Vision Pro | `Device.appleVisionPro` |
| Apple Vision Pro (M5) | `Device.appleVisionProM5` |

### Bug fixes

Expand Down
62 changes: 46 additions & 16 deletions Source/Device.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,15 @@ public enum Device {
///
/// ![Image]()
case appleWatchSeries11_46mm
#elseif os(visionOS)
/// Device is an [Apple Vision Pro](https://support.apple.com/kb/SP911)
///
/// ![Image]()
case appleVisionPro
/// Device is an [Apple Vision Pro (M5)](https://support.apple.com/en-us/125436)
///
/// ![Image]()
case appleVisionProM5
#endif

/// Device is [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)
Expand Down Expand Up @@ -774,8 +783,12 @@ public enum Device {
default: return unknown(identifier)
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return unknown(identifier)
switch identifier {
case "RealityDevice14,1": return appleVisionPro
case "RealityDevice17,1": return appleVisionProM5
case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "visionOS"))
default: return unknown(identifier)
}
#else
return unknown(identifier)
#endif
Expand Down Expand Up @@ -1344,6 +1357,16 @@ public enum Device {
public var hasForceTouchSupport: Bool {
return isOneOf(Device.allWatchesWithForceTouchSupport) || isOneOf(Device.allWatchesWithForceTouchSupport.map(Device.simulator))
}
#elseif os(visionOS)
/// All Vision devices
public static var allVisions: [Device] {
return [.appleVisionPro, .appleVisionProM5]
}

/// All simulator Vision devices
public static var allSimulatorVisions: [Device] {
return allVisions.map(Device.simulator)
}
#endif

/// Returns whether the current device is a SwiftUI preview canvas
Expand All @@ -1365,8 +1388,7 @@ public enum Device {
#elseif os(watchOS)
return allWatches
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return []
return allVisions
#else
return []
#endif
Expand Down Expand Up @@ -1636,7 +1658,6 @@ public enum Device {
#elseif os(tvOS)
return nil
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return nil
#else
return nil
Expand Down Expand Up @@ -1821,8 +1842,12 @@ extension Device: CustomStringConvertible {
case .unknown(let identifier): return identifier
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "Apple Vision Pro"
switch self {
case .appleVisionPro: return "Apple Vision Pro"
case .appleVisionProM5: return "Apple Vision Pro (M5)"
case .simulator(let model): return "Simulator (\(model.description))"
case .unknown(let identifier): return identifier
}
#else
switch self {
case .simulator(let model): return "Simulator (\(model.description))"
Expand Down Expand Up @@ -1986,8 +2011,12 @@ extension Device: CustomStringConvertible {
case .unknown(let identifier): return identifier
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "Apple Vision Pro"
switch self {
case .appleVisionPro: return "Apple Vision Pro"
case .appleVisionProM5: return "Apple Vision Pro (M5)"
case .simulator(let model): return "Simulator (\(model.safeDescription))"
case .unknown(let identifier): return identifier
}
#else
switch self {
case .simulator(let model): return "Simulator (\(model.safeDescription))"
Expand Down Expand Up @@ -2508,7 +2537,7 @@ extension Device {
extension Device {

public enum CPU: Comparable {
#if os(iOS) || os(tvOS)
#if os(iOS) || os(tvOS) || os(visionOS)
case a4
case a5
case a5X
Expand Down Expand Up @@ -2707,8 +2736,12 @@ extension Device {
case .unknown: return .unknown
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return .unknown
switch self {
case .appleVisionPro: return .m2
case .appleVisionProM5: return .m5
case .simulator(let model): return model.cpu
case .unknown: return .unknown
}
#else
return .unknown
#endif
Expand All @@ -2719,7 +2752,7 @@ extension Device.CPU: CustomStringConvertible {

/// A textual representation of the device.
public var description: String {
#if os(iOS) || os(tvOS)
#if os(iOS) || os(tvOS) || os(visionOS)
switch self {
case .a4: return "A4"
case .a5: return "A5"
Expand Down Expand Up @@ -2768,9 +2801,6 @@ extension Device.CPU: CustomStringConvertible {
case .s10: return "S10"
case .unknown: return "unknown"
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "unknown"
#else
return "unknown"
#endif
Expand Down
71 changes: 55 additions & 16 deletions Source/Device.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ tvs = [
Device("appleTV4K3", "Device is an [Apple TV 4K (3rd generation)](https://support.apple.com/kb/SP886)", "https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/SP886/apple-tv-4k-3gen_2x.png", ["AppleTV14,1"], 0, (), "Apple TV 4K (3rd generation)", "Apple TV 4K (3rd generation)", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, False, "a15Bionic", False, False),
]

# visionOS
visions = [
Device("appleVisionPro", "Device is an [Apple Vision Pro](https://support.apple.com/kb/SP911)", "", ["RealityDevice14,1"], 0, (1, 1), "Apple Vision Pro", "Apple Vision Pro", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, True, "m2", True, False),
Device("appleVisionProM5", "Device is an [Apple Vision Pro (M5)](https://support.apple.com/en-us/125436)", "", ["RealityDevice17,1"], 0, (1, 1), "Apple Vision Pro (M5)", "Apple Vision Pro (M5)", -1, False, False, False, False, False, False, False, False, False, False, 0, False, 0, True, "m5", True, False),
]

# watchOS
watches = [
Device(
Expand Down Expand Up @@ -361,6 +367,7 @@ watches = [
iOSDevices = iPods + iPhones + iPads + homePods
tvOSDevices = tvs
watchOSDevices = watches
visionOSDevices = visions
}%
#if os(watchOS)
import WatchKit
Expand Down Expand Up @@ -422,6 +429,13 @@ public enum Device {
///
/// ![Image](${device.imageURL})
case ${device.caseName}
% end
#elseif os(visionOS)
% for device in visionOSDevices:
/// ${device.comment}
///
/// ![Image](${device.imageURL})
case ${device.caseName}
% end
#endif

Expand Down Expand Up @@ -484,8 +498,13 @@ public enum Device {
default: return unknown(identifier)
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return unknown(identifier)
switch identifier {
% for device in visionOSDevices:
case ${', '.join(list(map(lambda device: "\"" + device + "\"", device.identifiers)))}: return ${device.caseName}
% end
case "i386", "x86_64", "arm64": return simulator(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "visionOS"))
default: return unknown(identifier)
}
#else
return unknown(identifier)
#endif
Expand Down Expand Up @@ -806,6 +825,16 @@ public enum Device {
public var hasForceTouchSupport: Bool {
return isOneOf(Device.allWatchesWithForceTouchSupport) || isOneOf(Device.allWatchesWithForceTouchSupport.map(Device.simulator))
}
#elseif os(visionOS)
/// All Vision devices
public static var allVisions: [Device] {
return [${', '.join(list(map(lambda device: "." + device.caseName, visionOSDevices)))}]
}

/// All simulator Vision devices
public static var allSimulatorVisions: [Device] {
return allVisions.map(Device.simulator)
}
#endif

/// Returns whether the current device is a SwiftUI preview canvas
Expand All @@ -827,8 +856,7 @@ public enum Device {
#elseif os(watchOS)
return allWatches
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return []
return allVisions
#else
return []
#endif
Expand Down Expand Up @@ -974,7 +1002,6 @@ public enum Device {
#elseif os(tvOS)
return nil
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return nil
#else
return nil
Expand Down Expand Up @@ -1034,8 +1061,13 @@ extension Device: CustomStringConvertible {
case .unknown(let identifier): return identifier
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "Apple Vision Pro"
switch self {
% for device in visionOSDevices:
case .${device.caseName}: return "${device.description}"
% end
case .simulator(let model): return "Simulator (\(model.description))"
case .unknown(let identifier): return identifier
}
#else
switch self {
case .simulator(let model): return "Simulator (\(model.description))"
Expand Down Expand Up @@ -1074,8 +1106,13 @@ extension Device: CustomStringConvertible {
case .unknown(let identifier): return identifier
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "Apple Vision Pro"
switch self {
% for device in visionOSDevices:
case .${device.caseName}: return "${device.safeDescription}"
% end
case .simulator(let model): return "Simulator (\(model.safeDescription))"
case .unknown(let identifier): return identifier
}
#else
switch self {
case .simulator(let model): return "Simulator (\(model.safeDescription))"
Expand Down Expand Up @@ -1568,7 +1605,7 @@ watchOS_cpus = [
extension Device {

public enum CPU: Comparable {
#if os(iOS) || os(tvOS)
#if os(iOS) || os(tvOS) || os(visionOS)
% for cpu in iOS_cpus:
case ${cpu.name}
% end
Expand Down Expand Up @@ -1607,8 +1644,13 @@ extension Device {
case .unknown: return .unknown
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return .unknown
switch self {
% for device in visionOSDevices:
case .${device.caseName}: return .${device.cpu}
% end
case .simulator(let model): return model.cpu
case .unknown: return .unknown
}
#else
return .unknown
#endif
Expand All @@ -1619,7 +1661,7 @@ extension Device.CPU: CustomStringConvertible {

/// A textual representation of the device.
public var description: String {
#if os(iOS) || os(tvOS)
#if os(iOS) || os(tvOS) || os(visionOS)
switch self {
% for cpu in iOS_cpus:
case .${cpu.name}: return "${cpu.description}"
Expand All @@ -1633,9 +1675,6 @@ extension Device.CPU: CustomStringConvertible {
% end
case .unknown: return "unknown"
}
#elseif os(visionOS)
// TODO: Replace with proper implementation for visionOS.
return "unknown"
#else
return "unknown"
#endif
Expand Down
26 changes: 26 additions & 0 deletions Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -819,4 +819,30 @@ class DeviceKitTests: XCTestCase {

#endif

// MARK: - visionOS
#if os(visionOS)

func testMapFromIdentifier() {
XCTAssertEqual(Device.mapToDevice(identifier: "RealityDevice14,1"), .appleVisionPro)
XCTAssertEqual(Device.mapToDevice(identifier: "RealityDevice17,1"), .appleVisionProM5)
}

func testDeviceCPU() {
XCTAssertEqual(Device.appleVisionPro.cpu, Device.CPU.m2)
XCTAssertEqual(Device.appleVisionProM5.cpu, Device.CPU.m5)
}

func testDescription() {
XCTAssertEqual(Device.appleVisionPro.description, "Apple Vision Pro")
XCTAssertEqual(Device.appleVisionProM5.description, "Apple Vision Pro (M5)")
}

func testSafeDescription() {
for device in Device.allRealDevices {
XCTAssertEqual(device.description, device.safeDescription)
}
}

#endif

}
Loading