swiftactor

Solve Main actor-isolated static property inside a Package


I'm wondering how to solve the Main actor-isolated class property 'current' can not be referenced from a nonisolated context Swift 6 issue inside a Swift Package.

In this package, I'm exposing a public struct that collects some device information. Unfortunately, now the UIDevice class is only accessible as @MainActor and the information I want to expose should be used even from parallel threads.

All the collected information can be eventually be calculated/collected at the start of the application that uses the package but I'm wondering how to do this properly.

This is a rough example of the current state:

public struct DeviceInfo: Codable, Equatable {

    let someVariable: String

    public static var current: APIDeviceInfo {
        DeviceInfo(
            // This is rising the issue `Main actor-isolated class property 'current' can not be referenced from a nonisolated context`
            someVariable: UIDevice.current...
        )
    }
}

My objective is to use this structure even from non-main threads.


Solution

  • In the end, thanks to the suggestions, I solved in this way:

    Removed the static variable from the data class:

    struct DeviceInfo: Codable, Equatable {
        let someVariable: String
    }
    

    Created a new structure that contains this DeviceInfo and has a @MainActor function to load this and other similar structures used by the package:

    public enum MyPackageConfig {
    
        // empty initialization
        fileprivate(set) static nonisolated(unsafe) var myDeviceInfo: DeviceInfo = DeviceInfo(someVariable: "")
    
        @MainActor
        public static func setup() {
            myDeviceInfoStruct = DeviceInfo(
                someVariable: UIDevice.current....
            )
        }
    }
    

    Switched all of the Package's internal DeviceInfo references to MyPackageConfig.myDeviceInfo.

    Finally I call the setup function in the SplashScreen during the startup operations to fully configure the Package and all of its needs:

    MyPackageConfig.setup()
    

    BTW: It would be better to have dependency injection here to have a solved dependency instead of the enum, but sadly I don't have the time at the moment.