SwiftUI - How to pass EnvironmentObject into View Model?

后端 未结 5 1995
甜味超标
甜味超标 2020-12-08 18:56

I\'m looking to create an EnvironmentObject that can be accessed by the View Model (not just the view).

The Environment object tracks the application session data, e

5条回答
  •  一生所求
    2020-12-08 19:53

    You shouldn't. It's a common misconception that SwiftUI works best with MVVM.

    MVVM has no place in SwfitUI. You are asking that if you can shove a rectangle to

    fit a triangle shape. It wouldn't fit.

    Let's start with some facts and work step by step:

    1. ViewModel is a model in MVVM.

    2. MVVM does not take value type (e.g.; no such thing in java)into consideration.

    3. A value type model (model without state) is considered safer than reference

      type model (model with state) in the sense of immutability.

    Now, MVVM requires you to set up a model in such way that whenever it changes, it

    updates view in some pre-determined way. This is known as binding.

    Without binding, you won't have nice separation of concerns, e.g.; refactoring out

    model and associated states and keeping them separate from view.

    These are the two things most iOS MVVM developers fail:

    1. iOS has no "binding" mechanism in traditional java sense.

      Some would just ignore binding, and think calling an object ViewModel

      automagically solves everything; some would introduce KVO-based Rx, and

      complicate everything when MVVM is supposed to make things simpler.

    2. model with state is just too dangerous

      because MVVM put too much emphasis on ViewModel, too little on state management

      and general disciplines in managing Control; most of the developers end up

      thinking a model with state that is used to update view is reusable and

      testable.

      this is why Swift introduces value type in the first place; a model without

      state.

    Now to your question: you ask if your ViewModel can have access to EnvironmentObject (EO)?

    You shouldn't. Because in SwiftUI a model that conforms to View automatically have

    reference to EO. E.g.;

    struct Model: View {
        @EnvironmentObject state: State
        // automatic binding in body
        var body: some View {...}
    }
    

    I hope people can appreciate how compact SDK is designed.

    In SwiftUI, MVVM is automatic. There's no need for a separate ViewModel object

    that manually binds to view which requires an EO reference passed to it.

    The above code is MVVM. E.g.; a model with binding to view.

    But because model is value type, so instead of refactoring out model and state as

    view model, you refactor out control (in protocol extension, for example).

    This is official SDK adapting design pattern to language feature, rather than just

    enforcing it. Substance over form.

    Look at your solution, you have to use singleton which is basically global. You

    should know how dangerous it is to access global anywhere without protection of

    immutability, which you don't have because you have to use reference type model!

    TL;DR

    You don't do MVVM in java way in SwiftUI. And the Swift-y way to do it is no need

    to do it, it's already built-in.

    Hope more developer see this since this seemed like a popular question.

提交回复
热议问题