3

I'm learning SwiftUI and my focus at the moment is to implement a method which I'm able to implement using UIKit. I need to create a method the determines whether I should Push the View or Present modally the view based on the value of a boolean.

In UIKit, my code is:

var presentVC = true // boolean that determines whether VC will be presented or pushed

let vc = ViewController() //Your VC that will be pushed or presented

if (presentVC == true) {
     self.presentViewController(vc, animated: true, completion: nil)
} else {
    self.navigationController.pushViewController(vc, animated: true)
}

But in SwiftUI, I'm not sure how to implement this correctly using the:

  • NavigationLink - For pushing the View
  • .sheet(isPresented:, content:) - For presenting the View modally

It seems that the NavigationLink and .sheet modifier is coupled with the view implementation. Does anyone already encountered and solve this scenario in SwiftUI? Thanks

I'm using SwiftUI 1.0 as I need to support iOS 13.

1 Answers1

5

A possible solution is to create a custom enum with available presentation types:

enum PresentationType {
    case push, sheet // ...
}

and create a custom binding for activating different views:

func showChildView(presentationType: PresentationType) -> Binding<Bool> {
    .init(
        get: { self.showChildView && self.presentationType == presentationType },
        set: { self.showChildView = $0 }
    )
}

Full code:

struct ContentView: View {
    @State var presentationType = PresentationType.push
    @State var showChildView = false

    func showChildView(as presentationType: PresentationType) -> Binding<Bool> {
        .init(
            get: { self.showChildView && self.presentationType == presentationType },
            set: { self.showChildView = $0 }
        )
    }

    var body: some View {
        NavigationView {
            VStack {
                Button(action: {
                    self.presentationType = .push
                    self.showChildView = true
                }) {
                    Text("Present new view as Push")
                }
                Button(action: {
                    self.presentationType = .sheet
                    self.showChildView = true
                }) {
                    Text("Present new view as Sheet")
                }
            }
            .navigationBarTitle("Main view", displayMode: .inline)
            .background(
                NavigationLink(
                    destination: ChildView(),
                    isActive: self.showChildView(presentationType: .push),
                    label: {}
                )
            )
        }
        .sheet(isPresented: self.showChildView(presentationType: .sheet)) {
            ChildView()
        }
    }
}

struct ChildView: View {
    var body: some View {
        ZStack {
            Color.red
            Text("Child view")
        }
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209