12

I need to pass a parameter calledFrom to a Sheet in SwiftUI.
Strangely, the parameter is not used on the first call, but it works on the following ones.

import SwiftUI

struct ContentView: View {
    @State var showSheet = false
    @State var calledFrom = -1
    
    var body: some View {
        ForEach((1...4), id: \.self) { i in
            getButton(i)
        }
        .sheet(isPresented: $showSheet) { Dialog(calledFrom: calledFrom) }
        .padding()
    }
    
    func getButton(_ i : Int) -> some View {
        return Button("\(i)"){print("Button \(i) pressed"); calledFrom = i; showSheet = true }
    }
}

struct Dialog: View {
  var calledFrom : Int
  @Environment(\.presentationMode) private var presentationMode
  var body: some View {
    VStack{
      Text("Called from Button \(calledFrom)")
        Button("close"){presentationMode.wrappedValue.dismiss()}
    }
    .padding()
  }
}
1

1 Answer 1

20

You have to use sheet(item:) to get the behavior you're looking for. In iOS 14, the sheet view is calculated before the @State changes:


struct ActiveItem : Identifiable {
    var calledFrom: Int
    var id: Int { return calledFrom }
}

struct ContentView: View {
    @State var activeItem : ActiveItem?
    
    var body: some View {
        ForEach((1...4), id: \.self) { i in
            getButton(i)
        }
        .sheet(item: $activeItem) { item in
            Dialog(calledFrom: item.calledFrom)
        }
        .padding()
    }
    
    func getButton(_ i : Int) -> some View {
        return Button("\(i)"){
            print("Button \(i) pressed");
            activeItem = ActiveItem(calledFrom: i)
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Is there a way to have ActiveItem nullable? Why? Because I need there either create new object or edit existing one. This is totally the same layout and the only difference is ActiveItem is nill or not.
It’s already an optional in my answer
it is nullable, but sheet(item will not be called if there is a nil value...🤷🏼‍♂️
You could put the value you want inside another wrapper struct and make the inner value optional

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.