Swiftui Sheet Shows Sheet with Wrong Data

SwiftUI sheet shows sheet with wrong data

You need to create one sheet instead of multiple sheets.

If you want to use .sheet(isPresented:content:) you can do the following:

struct ContentView: View {
var numbers = [1, 2, 3]
@State private var selectedNumber: Int?

var body: some View {
List(numbers, id: \.self) { number in
Text("number: \(number)")
.onTapGesture {
self.selectedNumber = number
}
}
.sheet(isPresented: binding) {
Text("This is a sheet number \(self.selectedNumber ?? 0)")
}
}

var binding: Binding<Bool> {
.init(
get: { self.selectedNumber != nil },
set: { _ in }
)
}
}

Alternatively you can use .sheet(item:content:):

struct Model: Identifiable {
let id: Int
}

struct ContentView: View {
var numbers = [1, 2, 3].map(Model.init)
@State private var selectedNumber: Model?

var body: some View {
List(numbers, id: \.id) { number in
Text("number: \(number.id)")
.onTapGesture {
self.selectedNumber = number
}
}
.sheet(item: $selectedNumber) { item in
Text("This is a sheet number \(item.id)")
}
}
}

EDIT

If you decide to use .sheet(item:content:) you can add an extension to Int (instead of creating a custom struct conforming to Identifiable):

extension Int: Identifiable {
public var id: Int { self }
}

as proposed in Asperi's answer.

.sheet in SwiftUI strange behaviour when passing a variable

This is known behaviour of sheet since SwiftUI 2.0. Content is created in time of sheet created not in time of showing. So the solution can be either to use .sheet(item:... modifier or passing binding in sheet content view (which is kind of reference to state storage and don't need to be updated).

Here is a demo of possible approach. Prepared with Xcode 12.4.

struct SignInView2: View {

@Environment(\.presentationMode) var presentationMode
@State private var invitationUrl: URL? // by default is absent

var body: some View {
VStack {
Text("Share Screen")

Button(action: {
print("link: \(invitationUrl)")
self.invitationUrl = createLink() // assignment activates sheet
}) {
Text("Share")
}
.sheet(item: $invitationUrl) {
ActivityView(activityItems: [$0] as [Any], applicationActivities: nil)
}
}
}
}

// Needed to be used as sheet item
extension URL: Identifiable {
public var id: String { self.absoluteString }
}

SwiftUI Issues with sheet modifier

.sheet being embedded inside a List does only open once is a known bug and I hope they fix it. Until then you have to move .sheet outside of any List.

But since the .sheet is not inside a List but inside a NavigationView, it might a good idea to try to move the .sheet outside of it.

But do not attach two .sheet two the same View, but add them the following way instead:

VStack{
NavigationView{ ... }
Text("").hidden().sheet(...)
Text("").hidden().sheet(...)
}

SwiftUI Sheet not updating variable

Create a binding with an optional workout. Nil will be the case that the sheet is not presented, assigning a workout to this variable displays the corresponding sheet.

struct WorkoutList: View {
private var workouts = workoutData
@State var selectedWorkout: Workout?

var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(workouts) { workoutCard in
GeometryReader { geometry in
Button(action: { self.selectedWorkout = workoutCard }) {
WorkoutCardView(workout: workoutCard).rotation3DEffect(Angle(degrees: Double((geometry.frame(in: .global).minX - 30) / -30)), axis: (x: 0, y: 10, z: 0)).sheet(item: self.$selectedWorkout) { workout in
WorkoutDetails(workout: workout)
}
}
}.frame(width:246, height: 360)
}
}.padding(30)
}
}
}

Why does my sheet open before my data is set?

I found a solution:

.sheet(item: $dataToSend) { item in
MyView(data: item)
}
.onOpenURL { url in
ApiCall.getData(from: url) { dataFromApi in
self.dataToSend = dataFromApi
}
}

Sheet is now opened as soon as "dataToSend" is set, and this is perfect

SwiftUI: .sheet() doesn't go to the previous view with expected data when dismiss current sheet

There should be only one .sheet in view stack, but in provided snapshot there are many which activated all at once - following behaviour is unpredictable, actually.

Here is corrected variant

struct MovieListView: View {
var movies: [PersonMovieViewModel]
@State private var showSheet = false
@State private var selectedID = "" // type of your movie's ID

var body: some View {
ScrollView() {
HStack() {
ForEach(movies) { movie in
VStack() {
Image(...)
.onTapGesture {
self.selectedID = movie.id
self.showSheet.toggle()
}
}
}
}
.sheet(isPresented: $showSheet) {
SingleMovieView(movieId: selectedID)
}
}
}
}

SwiftUI sheet doesn't access the latest value of state variables on first appearance

You see value on time of sheet creation. If you want to track parent view state create sheet subview with binding to that state, like below. Binding will update subview when subview will appear.

Tested with Xcode 12 / iOS 14

Re-tested with Xcode 13.3 / iOS 15.4

struct DemoView: View {
@State var showDetails: Bool = false
var body: some View {
VStack {
Button(action: {
showDetails = true
}) {
Text("Show sheet")
}
}.sheet(isPresented: $showDetails){
SheetDetailView(flag: $showDetails)
}
}
}

struct SheetDetailView: View {
@Binding var flag: Bool
var body: some View {
VStack {
Text("showDetails: \(flag ? "yes" : "no")")
}
}
}


Related Topics



Leave a reply



Submit