UIDevice: Main actor-isolated class property 'current' can not be referenced from a non-isolated context

I have a Safari Web Extension for visionOS that reads from UIDevice.current.systemVersion in order to provide the OS version number back to the JavaScript context utilizing beginRequest(with:).

When switching my project to use Swift 6, I received this obscure error:

Main actor-isolated class property 'current' can not be referenced from a non-isolated context

Class property declared here (UIKit.UIDevice)

Add '@MainActor' to make instance method 'beginRequest(with:)' part of global actor 'MainActor'

Adding @MainActor causes another issue (Main actor-isolated instance method 'beginRequest(with:)' cannot be used to satisfy nonisolated protocol requirement) which suggests adding @preconcurrency to NSExtensionRequestHandling which then breaks at Non-sendable type 'NSExtensionContext' in parameter of the protocol requirement satisfied by main actor-isolated instance method 'beginRequest(with:)' cannot cross actor boundary.

What's the proper solution here?

Here's a simplified snippet of my code:

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
  func beginRequest(with context: NSExtensionContext) {
    // ...

    var systemVersionNumber = ""
    systemVersionNumber = UIDevice.current.systemVersion

    // ...
  }
}

Since UIDevice is only supported on the main thread, we would likely recommend you use NSProcessInfo instead, or cache this value once early on before it is needed.

Thank you, @Frameworks Engineer!

In my case your comment helped me a lot. In my app I need to differentiate an iPhone device from other devices like iPad, Mac, etc. because on iPhone I must not select by default first element in my Navigation List, but I must do this on other devices.

Initially I was checking like this:

if !UIDevice.current.model.starts(with: "iPhone") { ... }

but it showed me this warning "Main actor-isolated class property 'current' can not be referenced from a non-isolated context; this is an error in Swift 6" for such check within the (try? await ...) block. I was curious why, but now I understand, it's because UIDevice is only supported on the main thread.

So, now I'm getting the value at once in the beginning:

private let device = UIDevice.current.model

and then just check the device in other places:

if !device.starts(with: "iPhone") { ... }
now I'm getting the value at once in the beginning

Cool.

However, I’m concerned about you using the model string to set up your UI. There are usually better ways to this. I recommend that you start by looking at the userInterfaceIdiom property.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

UIDevice: Main actor-isolated class property 'current' can not be referenced from a non-isolated context
 
 
Q