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
Return Object for a Method Inside Completion Block
Sending Array Data from One View Controller to Another
Skphysicscontact Not Detecting Categorybitmask Collision
How to Draw Something on a PDF in Swift
Sharing Screenshot of Swiftui View Causes Crash
Swift: Change Speed of a Moveto Skaction
Mac App Disappears When Window Is Closed Then Another App Is Selected
How to Add a Storage Reference in Swift for Firestore
Filter by Day from Nsdate in Realm, Swift
In Swift Can You Trap "Fatal Error Unexpectedly Found Nil While Unwrapping an Optional Value"
Include Inheritance Constraint in Swift Generic Types
Msmessagelivelayout Freeze/Crash in Transcript When Info.Plist Contains Privacy Request
How to Create Travelling Wave in Spritekit
Spritekit: Sprites Are Moving Through Each Other with a Physicsbody Already Set
Uibutton State Changing While Scrolling The Tableview with Multiple Sections - Swift