Skip to content

Instantly share code, notes, and snippets.

@joemasilotti
Last active October 13, 2021 03:20
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joemasilotti/b90d89cc8e78440bf21c25ce512a72b1 to your computer and use it in GitHub Desktop.
Save joemasilotti/b90d89cc8e78440bf21c25ce512a72b1 to your computer and use it in GitHub Desktop.
Multiple sheets in SwiftUI
class SettingsSheet: SheetState<SettingsSheet.State> {
enum State {
case attributions
case email
case feedback
case instructions
case licenseAgreement
case privacyPolicy
}
}
struct SettingsView: View {
@ObservedObject var sheet = SettingsSheet()
var body: some View {
VStack {
Button("Attributions") { self.sheet.state = .attributions }
Button("Email") { self.sheet.state = .email }
Button("Feedback") { self.sheet.state = .feedback }
Button("Instructions") { self.sheet.state = .instructions }
Button("License Agreement") { self.sheet.state = .licenseAgreement }
Button("Privacy Policy") { self.sheet.state = .privacyPolicy }
}
.sheet(isPresented: $sheet.isShowing, content: sheetContent)
}
@ViewBuilder
private func sheetContent() -> some View {
if sheet.state == .attributions {
AttributionsView()
} else if sheet.state == .email {
EmailView()
} else if sheet.state == .feedback {
FeedbackView()
} else if self.sheet.state == .instructions {
InstructionsView()
} else if self.sheet.state == .licenseAgreement {
WebView(url: Policy.licenseURL)
} else if self.sheet.state == .privacyPolicy {
WebView(url: Policy.privacyURL)
} else {
EmptyView()
}
}
}
import Combine
class SheetState<State>: ObservableObject {
@Published var isShowing = false
@Published var state: State? {
didSet { isShowing = state != nil }
}
}
@fespinoza
Copy link

well written post/examples!

@fespinoza
Copy link

also I guess in the buttons you were mean to write

Button("Attributions") { self.sheet.state = .attributions }

@joemasilotti
Copy link
Author

Thanks @fespinoza.

You're correct, I updated the gist. Great catch!

@UlricusR
Copy link

I like your solution. How would you best implement a “Done” button inside the sheet? Pass $sheet.isShowing as Binding to the SheetView?

@joemasilotti
Copy link
Author

Exactly, @UlricusR! I'm doing the same for a confirmation button in a form-style sheet.

@UlricusR
Copy link

UlricusR commented Oct 1, 2020

As I still had issues with conflicting Bindings to other Observable Objects with your final and your pre-final solution (the one without the SheetState class), I posted this on StackOverflow with a - in my eyes - very elegant solution, as you can even get rid of the SheetState class this way:

https://stackoverflow.com/questions/64139912/swiftui-state-property-is-not-updated

To close the sheet, I followed this post:

https://daddycoding.com/2020/03/01/swiftui-sheet-modals/

At the end, I combined your solution with the other two. Thanks again!

@joemasilotti
Copy link
Author

Very nice! Do you have a version for iOS 13?

@UlricusR
Copy link

Well, the App I use it for has target iOS 13.5 and above, so yes, it should work for iOS 13. You can see it in action e.g. in FoodList.swift in my repo https://github.com/UlricusR/iOS-EasyFPU

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment