Reputation: 13
I am trying to solve an issue with DismissAction in Preview. This is in the View: let parentDismiss: DismissAction
This is what I have in Preview:
struct MilkingView_Previews: PreviewProvider {
static var previews: some View {
MilkingView(parentDismiss: DismissAction())
}
}
But I constantly have an error 'DismissAction' cannot be constructed because it has no accessible initializers
DismissAction() doesn't help as well as DismissAction.
Upvotes: 1
Views: 674
Reputation: 339
on iOS 17 you have @Previewable
that lets you add an environment variable to the preview section. On older versions of iOS, you will get a warning for this.
#Preview {
@Previewable @Environment(\.dismiss) var dismiss
MilkingView(parentDismiss: dismiss)
}
Upvotes: 0
Reputation: 1
Declare let parentDismiss: DismissAction?
.
In the app parentDismiss
is non-nil, in Preview set it to nil.
Upvotes: 0
Reputation: 87
Incredibly, I've found all you need is to ignore the property altogether. The following code compiles & clicking the dismiss button performs no action at all.
import SwiftUI
struct MySheet: View {
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationStack {
VStack {
Text("It worked!")
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
}
}
}
#Preview {
MySheet()
}
Upvotes: 0
Reputation: 247
For other's who come across this. Define your dismiss action in the struct as a static property.
@Environment(\.dismiss) static private var dismiss
Upvotes: 1
Reputation: 1986
I don't know how to solve your problem the right way, but I am using a workaround, and it works for me.
So, bear with me.
I have a .sheet
that has a view inside. That view has a list of NavigationLink
items, and they will open a form in a third view. From that form I should be able to close the sheet.
So..
Main view > List (in a sheet) > Form (close from here)
So on my list view I have this:
@Environment(\.dismiss) var dismiss
// (...)
NavigationLink {
MyForm(something, dismissParent: dismiss)
} label: {
Text(title)
}
On my form view, that lives inside that list, I pass my dismiss into the initialiser. The init originally looked like this:
private var dismissParent: DismissAction
init(_ something, dismissParent: DismissAction) {
self.something = something
self.dismissParent = dismissParent
}
Of course, that breaks the preview, as your own code. What I did was pass a closure as a callback. So I modified my code, like so:
private var dismissParent: () -> Void
init(_ something, dismissParent: @escaping () -> Void) {
self.something = something
self.dismissParent = dismissParent
}
On the parent I got this:
@Environment(\.dismiss) var dismiss
// (...)
NavigationLink {
MyForm(something) {
dismiss()
}
} label: {
Text(title)
}
And on the preview I do:
#if DEBUG
struct MyForm_Previews: PreviewProvider {
static var previews: some View {
ZStack {
MyForm(
dummySomething,
dismissParent: {}
)
}
}
}
#endif
I use that ZStack
there because preview for some reason seems to break a lot when I'm dealing with views in sheets. I don't know why, but this fixes it.
I also use annotation #if DEBUG
and #endif
because I realised that the preview code is compiled in some situations and it bloats the app needlessly. I use that to exclude preview from the final code. (I don't know if that was fixed or not, I don't have time or patience to pursue this kind of information, but it doesn't break my code, so I'm happy.)
It works for me. Try that.
Upvotes: 0
Reputation: 9675
This should be enough to make the preview build, if you simply need to provide a function, but don't need it to actually do anything:
struct MilkingView_Previews: PreviewProvider {
static var previews: some View {
MilkingView(parentDismiss: {})
}
}
if you do, you can always do something like:
struct MilkingView_Previews: PreviewProvider {
static var previews: some View {
MilkingView(parentDismiss: {
print("Doing something...")
})
}
}
There is no need to do more than this. It is a preview provider showing just part of the UI.
Upvotes: 1