swiftuiasync-awaitpreview

How to create #Preview with async code in swiftUI?


I would like to be able to create a #Preview that uses some values that are computed with async/await.

Below is a sample code with the first 2 previews working fine. The last one calling an async func fails.

import SwiftUI
import SwiftData

struct TestUIView: View {
    
    var passedValue:String
    
    var body: some View {
        Text("passedValue: \(passedValue)")
    }
}


#Preview {
    let passedValue="My value"
    return TestUIView(passedValue: passedValue)
}

#Preview {
    let passedValue=MyClass.getValue()
    return TestUIView(passedValue: passedValue)
}

#Preview {
    var passedValue:String {
        get async {
            return await MyClass.getValueAsync()
        }
    }
    return TestUIView(passedValue: passedValue)
}



class MyClass {
    
    public class func getValue() -> String {
        return "from getValue"
    }
    
    public class func getValueAsync() async -> String {
        return "from getValueAsync"
    }
}

The Preview error is: Compiling failed: 'async' property access in a function that does not support concurrency

In the real app, the data passed on is created in async mode and once available passed on to the next View. I want to be able to use the same function that creates this data in the Preview, rather then creating some dummy data only for the #Preview.


Solution

  • The way you are going to solve this Preview Macro problem is the same way you would solve other issues such as using @State variables: create a view struct within the macro.

    #Preview("from getValueAsync") {
        
        struct AsyncTestView: View {
            
            @State var passedValue: String = ""
            
            var body: some View {
                TestUIView(passedValue: passedValue)
                    .task {
                        passedValue = await MyClass.getValueAsync()
                    }
            }
        }
        
        return AsyncTestView()
    }
    

    You can also create it outside of your preview, but then archiving would not strip the code when creating a release. Another thing, If you are using multiple macros, it helps to name them.