Learning to Refactor to EnvironmentObject

An exercise in Refactoring

I saw this article talking about the value of images showing how to choose the proper Swift Property Wrapper.  I cannot find the article nor the toot now... but it got me thinking... - see image at right (it does not enlighten this decision).

So now I'm attempting to refactor my App code and move a ViewModel into the Environment.  Let's see how this goes.  I may need to revert this attempt.


Inside the body of struct WatchListView: inside a sheet modifier I create a Chart_ViewModel.  This seems like a highly useful place to refactor and place the chart view model into the environment.  Let's see if this call site gets simpler and more readable by this refactoring into the Environment.


StockChartDetail_View(chartVM: Chart_ViewModel(ticker: $0, apiService: quotesVM.stocksAPI),

                                quotesVM: .init(ticker: $0, stocksAPI: quotesVM.stocksAPI),

                                      transactionList: [], wlTicker: $0 )


So my first attempt to declare the Chart View Model as a StateObject runs into a few problems.  First it is a structure not an object.  Second it requires parameters - which gets me into the compiler error "Cannot use instance member 'wlTicker' within property initializer; property initializers run before 'self' is available".  See Saurn's article How to initialize @StateObject with parameters in SwiftUI.  Before I attempt to fix the initialization issue - I will revert all my edits and start from a fresh & building code base.

Revert!

I'm also learning to practice the Mikado Method.

Next attempt...

After reverting to a stable code base... I'm going to restart this refactoring at the discovered dependency Chart_ViewModel changing it to have all parameters with a coded default - so that it can be a properly created @StateObject.  Apple has recently (March 2023) updated the StateObject documentation with advice:  Initialize state objects using external data. I believe this applies here.

After the init() rework it is easy to make the Chart_ViewModel part of the App Environment.  Then it is also easy to rework the call sites to pull the view models from the environment instead of being passed into the views.

The one interesting change is making the view models update for the proper WLTicker.  This is accomplished by calling the new updateTicker() method in the view's onAppear() method's closure.

Now the call site is much simpler:

StockChartDetail_View(transactionList: [], wlTicker: $0 )

And it could be made a bit cleanner in the next round of clean up.