Michael Long
1 min readMar 15, 2024

--

Thanks for reading!

I'd first note that the GenericLoadingView pretty much does what you ask, eschewing the view model and illustrates a (relatively) simple view with a single state variable to drive it

The view model in the earlier example is rather simplistic, although it still demonstrates the common use case of taking information from an API call and then processing the result (In this case just data or empty) .

I live in the financial world and specific API calls frequently entail quite a bit of work setting up the request and processing the results into something palatable for consumption by a given view. And I prefer not to put such code in the view.

Localizations, analytics tracking, and a bunch of other stuff also typically lives there (but again, not for the article.)

The async load function is directly callable from .task and inherits the task cancellation state (though not checked in this example) and since it's async doesn't require setting up something like

func load() {

Task { ... }

}

Doing something like above lets the task escape and makes the vm load function harder to test. (We do a lot of tests.)

I've all for views w/o view models... but the second a view starts embedding business logic or hits a certain level of complexity that logic is moved to a vm so it can be tested.

Speaking of which, I'm not aware of any consistency issues with StateObject when used correctly, and especially any more so than using State. One simply needs to understand view identity and lifecycle.

--

--

Michael Long
Michael Long

Written by Michael Long

I write about Apple, Swift, and SwiftUI in particular, and technology in general. I'm also a Lead iOS Engineer at InRhythm, a modern digital consulting firm.

No responses yet