John Marc - Simple EnviormentObject and Published method to show different views

John Marc

Follow @ioloro on Micro.blog.

Simple EnviormentObject and Published method to show different views

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()
    }
}