iosswiftui

SwiftUI view parameter does not update as expected


I am curious why this .fullScreenCover display of a view does not update properly with a passed-in parameter unless the parameter is using the @Binding property wrapper. Is this a bug or intended behavior? Is this the fact that the view shown by the fullScreenCover is not lazily generated?

import SwiftUI

struct ContentView: View {
    @State private var showFullScreen = false
    @State private var message = "Initial Message"
    var body: some View {
        VStack {
            Button {
                self.message = "new message"
                showFullScreen = true
            } label: {
                Text("Show Full Screen")
            }

        }.fullScreenCover(isPresented: $showFullScreen) {
            TestView(text: message)
        }
    }
}

struct TestView: View {
    var text: String
    var body: some View {
       Text(text)
    }
}

Solution

  • There is a different .fullScreenCover(item:) for passing in dynamic data, the closure is changed whenever item changes. For more info see the docs and here is an example:

    import SwiftUI
    
    struct CoverData: Identifiable {
        var id: String {
            return message
        }
        let message: String
    }
    
    struct FullScreenCoverTestView: View {
        @State private var coverData: CoverData?
        
        var body: some View {
            VStack {
                Button {
                    coverData = CoverData(message: "new message")
                } label: {
                    Text("Show Full Screen")
                }
    
            }
            .fullScreenCover(item: $coverData, onDismiss: didDismiss) { item in
                TestView(text: item.message)
                .onTapGesture {
                    coverData = nil
                }
            }
        }
    
        func didDismiss() {
            // Handle the dismissing action.
        }
    
    }
    
    struct TestView: View {
        let text: String
        
        var body: some View {
           Text(text)
        }
    }