This gist accompanies a blog post on Masilotti.com, How to manage multiple sheets in SwiftUI.
Last active
October 13, 2021 03:20
-
-
Save joemasilotti/b90d89cc8e78440bf21c25ce512a72b1 to your computer and use it in GitHub Desktop.
Multiple sheets in SwiftUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SettingsSheet: SheetState<SettingsSheet.State> { | |
enum State { | |
case attributions | |
case email | |
case feedback | |
case instructions | |
case licenseAgreement | |
case privacyPolicy | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Combine | |
class SheetState<State>: ObservableObject { | |
@Published var isShowing = false | |
@Published var state: State? { | |
didSet { isShowing = state != nil } | |
} | |
} |
Very nice! Do you have a version for iOS 13?
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
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!