So, you’ve got a single view container, let’s call it “ControlCenter” that you want to show one of three sets of controls within. Typically you’d write three views, and try to intiatiate these views, push/pulling into focus.
With SwiftUI creating a centralized method where the views are unaware of when/why they will appear, but also the ability to summon these views should be possible by any other arbitrary portion of the app.
Enter @EnviormentObject and @Published
First lets create our data/control class:
// CommandCenterManager.swift
// Created by John Marc on 1/9/23.
class CommandCenterManager: ObservableObject {
@Published var currentView: CurrentView
init() {
currentView = .first
}
enum CurrentView {
case first, second, third
}
func getViewPosition(currView: CurrentView) -> Int {
var viewPosition = 0
if currView == .first {
viewPosition = 1
}
if currView == .second {
viewPosition = 2
}
if currView == .third {
viewPosition = 3
}
return viewPosition
}
func getNextView() {
let currentPos = getViewPosition(currView: self.currentView)
print("CurrentView: \(self.currentView)")
if currentPos == 1 {
currentView = .second
}
if currentPos == 2 {
currentView = .third
}
if currentPos == 3 {
currentView = .first
}
print("NextView: \(self.currentView)")
}
}
From there, on app creation let’s tell our app about this EnviormentObject:
// CommandCenterApp.swift
// Created by John Marc on 1/9/23.
import SwiftUI
@main
struct CommandCenterApp: App {
@StateObject var ccm = CommandCenterManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(ccm)
}
}
}
Excellent, let’s create the container to hold our views and the views themselves:
// CommandCenterViews.swift
// Created by John Marc on 1/9/23.
import Foundation
import SwiftUI
struct CurrentView: View {
@EnvironmentObject var ccm: CommandCenterManager
var body: some View {
switch ccm.currentView {
case .first:
FirstView()
case .second:
SecondView()
case .third:
ThirdView()
}
}
}
struct FirstView: View {
var body: some View {
VStack {
Text("FirstView")
}
.frame(width: 500, height: 500)
.background(.red)
}
}
struct SecondView: View {
var body: some View {
VStack {
Text("SecondView")
}
.frame(width: 500, height: 500)
.background(.green)
}
}
struct ThirdView: View {
var body: some View {
VStack {
Text("ThirdView")
}
.frame(width: 500, height: 500)
.background(.blue)
}
}
And finally the view that calls into this CurrentView
:
// ContentView.swift
// Created by John Marc on 1/9/23.
import SwiftUI
struct ContentView: View {
@EnvironmentObject var ccm: CommandCenterManager
var body: some View {
VStack {
CurrentView()
Button("Next View", action: {
ccm.getNextView()
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}