How to check if device is Vision Pro - Xcode 15 Beta 4
Asked Answered
P

9

6

I have a video analysis app and i'm trying to make it compatible with visionOS. It crashes because camera is not allowed; Apple only allows to import videos from Photos.

So I would need to check on launch if the device runs visionOS to show the photos picker rather than the camera view, similarly to what I use right now to check if I'm on macCatalyst or iOS:

#if targetEnvironment(macCatalyst)
   print("We are in macOS Catalyst")
#else
   print("We are in iOS")
#endif

Thanks in advance.

Piderit answered 25/7, 2023 at 7:3 Comment(3)
I would imagine it'd be #if os(visionOS). Can't find it documented though.Memoried
I tried that before posting but it doesn't work...Piderit
Does anybody figure it out after release of vision pro?Splendid
P
3

I've found a workaround with a piece of code here, created to detect iPhone/iPad models:

    func 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)
}

When calling it in viewDidLoad, it successfully detects the Vision Pro simulator as 'RealityDevice14,1'.

Piderit answered 27/7, 2023 at 6:46 Comment(4)
It remains to be seen which model identifier will be returned on a real Vision Pro device.Sawn
Sure, but it's unlikely Apple will break the established pattern here when it comes to the relationship between values in the simulator and actual device. And 14 is also consistent with M2-based Macs (e.g. Mac14,2). In lieu of proper API support from Apple (equivalent of ProcessInfo.isiOSAppOnMac), I don't see a better solution, so I would go with this (perhaps using sysctl in place of uname, as illustrated in https://mcmap.net/q/1631807/-is-there-a-way-to-get-the-iphone-model-using-sysctl).Erny
Unfortunately, this solution doesn't seem to work on a real device. We don't have one to check for sure, but our app didn't pass a compatibility check at Apple - the app tries to use unavailable APIs which we have restricted on Vision Pro, but the device check fails.Jewry
Here is a sample code that works on real device: gist.github.com/florentmorin/cbfe34dda1919c6fd7df9b93b5f276b9Mcginty
S
7

Compiler directives

Try os(visionOS) or os(xrOS). At the moment both names are correct.

#if os(visionOS)
   print("We are in visionOS")
#else
   print("We are NOT in visionOS")
#endif

Since 2023-09-18, os(visionOS) is the officially documented way.

Sexennial answered 25/7, 2023 at 11:58 Comment(5)
Thanks, but that's the first thing I tried and it doesn't work. It always print the "We are in iOS" message. Even though I'm running in visionOS simulator, it detects it as iOS. Maybe I'm missing something?Piderit
It depends where you put your preprocessor macros. I use it inside ContentView (#else statement is automatically dimmed out).Sexennial
I use it in the viewDidLoad method of a specific UIViewController, and it doesn’t work. UIdevice.model tells me it’s an iPad…Piderit
@Piderit The reason for this is that the UIKit app will run in iPad-compatible mode, whereas OS(xrOS) will return false.Peripatetic
If you're running Apple Vision Pro (Designed for iPad), no matter where you put this code it never returns TRUE.Palace
F
3

I believe you're running your iOS app directly on visionOS, without recompiling the code against the visionOS SDK, correct?

If so, the app is in compatible mode, and any conditional compile directives like #if os(xrOS) won't work. It's similar to an iOS app running on a Mac with Apple Silicon (check ProcessInfo.isiOSAppOnMac).

However, I haven't found a suitable API to determine if an iOS app is running on visionOS at runtime.

Forum Link: https://developer.apple.com/forums/thread/733029

UPDATE

  1. uname(&systemInfo) works on simulator but NOT on a physical device. ❌
var systemInfo = utsname()
uname(&systemInfo) // "iPad13,4" returned on a physical device
  1. Detect Camera ❌
UIImagePickerController.isCameraDeviceAvailable(.rear) // false on visionOS but also can be false for an restricted iOS device
Flavio answered 26/7, 2023 at 14:58 Comment(2)
Thanks a lot, Gong. You were correct. It seems that there are no options right now to check if an iOS app is running on Vision Pro. The only viable option at this point is to compile adding Vision Pro as a new device rather than using the compatibility mode. It will likely break parts of the code thoughPiderit
Hi again Gong, check my updated accepted answer. I've found a piece of code that detects the Vision Pro simulator as "RealityDevice". It might be helpful. CheersPiderit
P
3

I've found a workaround with a piece of code here, created to detect iPhone/iPad models:

    func 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)
}

When calling it in viewDidLoad, it successfully detects the Vision Pro simulator as 'RealityDevice14,1'.

Piderit answered 27/7, 2023 at 6:46 Comment(4)
It remains to be seen which model identifier will be returned on a real Vision Pro device.Sawn
Sure, but it's unlikely Apple will break the established pattern here when it comes to the relationship between values in the simulator and actual device. And 14 is also consistent with M2-based Macs (e.g. Mac14,2). In lieu of proper API support from Apple (equivalent of ProcessInfo.isiOSAppOnMac), I don't see a better solution, so I would go with this (perhaps using sysctl in place of uname, as illustrated in https://mcmap.net/q/1631807/-is-there-a-way-to-get-the-iphone-model-using-sysctl).Erny
Unfortunately, this solution doesn't seem to work on a real device. We don't have one to check for sure, but our app didn't pass a compatibility check at Apple - the app tries to use unavailable APIs which we have restricted on Vision Pro, but the device check fails.Jewry
Here is a sample code that works on real device: gist.github.com/florentmorin/cbfe34dda1919c6fd7df9b93b5f276b9Mcginty
S
2

For everyone who is wondering, the device name for the real Vision Pro is iPad13,4, not RealityDevice as in simulator. It has a .front camera, but does not have a .rear camera for UIImagePickerController.isCameraDeviceAvailable.

This means we are unable to tell a difference between a real iPad and the Vision Pro. The only option is to use a combination of checks for identifier + camera and wait for an equivalent of isiOSAppOnMac.

Splendid answered 8/2, 2024 at 15:9 Comment(0)
A
1

Actually it is not because camera is not allowed, it is because camera is not available on simulator. The best you can do, if you are building visionOS app using iOS SDK, you can check whether camera is available or not using availability check. This is actually much safer solution and works e.g. when camera is not available on some phone as well (iPhone simulator).

if UIImagePickerController.isCameraDeviceAvailable(.front) {
    ...
}

For more info see WWDC 2023 video.

Abeyta answered 7/9, 2023 at 8:33 Comment(0)
P
1

You can use

if !UIImagePickerController.isCameraDeviceAvailable(.rear) {
    // Vision Pro
}

.front comes up with true but rear comes up with false. It is fallible of course but since iPads all have rear cameras it should work.

Painting answered 7/2, 2024 at 19:2 Comment(0)
L
1

You can easily check whether the device is Vision Pro using:

UIDevice.current.userInterfaceIdiom == .vision 
Lath answered 21/5, 2024 at 10:21 Comment(0)
B
0

we can use

  @available(iOS 17.0, *)
    private static var supportsOpticsID: Bool {
        let authContext = LAContext()
        _ = authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
        return authContext.biometryType == .opticID
    }

it checks optics id device physical capability. returns true on real Vision Pro

Bromoform answered 1/5, 2024 at 1:36 Comment(0)
D
0

If you are looking for something similar to ProcessInfo.isiOSAppOnMac (i.e., is this running in "Designed for iPad" mode on a Vision Pro) that works on both simulator and a physical device:

extension ProcessInfo {

    var isiOSAppOnVisionPro: Bool {
#if targetEnvironment(simulator)
        return ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]?.hasPrefix("RealityDevice") ?? false
#else
        if #available(iOS 17, *) {
            let authContext = LAContext()
            _ = authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
            return authContext.biometryType == .opticID
        }
        else {
            return false
        }
#endif
    }

}
Discover answered 22/5, 2024 at 5:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.