Search code examples
concurrencyswiftui

how do I construct a swiftui class annotated mainactor in preview


So - I have a class called settings, that I use all over the place - and particularly want other views to react when stuff is changed. I've annotated it with @MainActor - and when running the app, it all works fine.

however, in a preview I just try and create an instance:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {        
        Group {
            ContentView( settings: Settings())
        }
    }
}

And suddenly, while the main program compiles and runs fine - the preview doesn't -

call to main actor-isolated initialiser 'init()' in a synchronous non isolated context.

Which I can get around with code like the following:

struct ContentView_Previews: PreviewProvider {
    
    var settings : Settings
    
    static func get_settings() -> Settings
    {
        var the_array : [Settings] =  []
        DispatchQueue.main.asyncAndWait( execute: DispatchWorkItem {
            the_array.append( Settings())
        })
        return the_array[0]
    }
    
    init()
    {
        self.settings = ContentView_Previews.get_settings()
    }
    
    static var previews: some View {        
        Group {
            ContentView( settings: Settings())
        }
    }
}

which is obviously ridiculous. I'm sure there's a better way - but don't know what it is - how can I do this in one or two lines, without having to make a helper function?

btw - THIS code crashes the preview provider every time:



struct ContentView_Previews: PreviewProvider {
        
    static func get_settings() -> Settings
    {
        var the_array : [Settings] =  []
        DispatchQueue.main.asyncAndWait( execute: DispatchWorkItem {
            the_array.append( Settings())
        })
        return the_array[0]
    }
  
    static var previews: some View {        
        Group {
            ContentView( settings: get_settings())
        }
    }
}

Solution

  • I was able to fix this issue by annotating the preview struct with @MainActor

    @MainActor
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {        
            Group {
                ContentView( settings: Settings())
            }
        }
    }