Home > front end >  SwiftUI MVVM tiny question from what I saw in a lecture
SwiftUI MVVM tiny question from what I saw in a lecture

Time:06-28

I was watching a lecture about MVVM in Swift and how it works, and I basically understood that the Model will contain data and logic, ViewModel passes that data to the View, maybe cleans it up a bit and the View can also call intent functions in the ViewModel to notify the Model of some things that need to be modified.

Now I know I don't really have much context but there are a bunch of lectures here and there's no way for me to really explain everything for now but basically we're making a memory card game and now we are now changing it to have a MVVM design pattern(It didn't have one before). The model currently contains a Card struct and a choose function to choose a card and stuff like that, but for some reason the lecturer puts an array of emojis(The content of the cards in this game) in the ViewModel and not the Model.

I thought that the Model should be the one that stores the data and not the ViewModel? Could anyone maybe try to explain why this was done?

ViewModel:

import SwiftUI



class EmojiMemoryGame //this is the ViewModel
{
    static let emojis = ["floaf","taco","george","chicken","squeaky","cat","dollar","a","b","c","d","e","f","g","h"] // these are supposed to be the emojis I just used some words instead.
    static func createMemoryGame() -> MemoryGame<String>
    {
        MemoryGame<String>(numbersOfPairsOfCards: 4) { pairIndex  in emojis[pairIndex]}
    }
    private var model : MemoryGame<String> = createMemoryGame()
    var cards: Array<MemoryGame<String>.Card>
    {
        model.cards
    }

}

Model:

import Foundation

struct MemoryGame<CardContent> //MemoryGame is the model for the MVVM pattern
{
    private(set) var cards : Array<Card>
    func choose(_ card: Card)
    {

    }

    init(numbersOfPairsOfCards: Int, createCardContent: (Int) -> CardContent)
    {
        cards = Array<Card>()
        //add numbersOfPairsOfCards*2 to cards array.
        for pairIndex in 0..<numbersOfPairsOfCards
        {
            let content = createCardContent(pairIndex)
            cards.append(Card(content: content))
            cards.append(Card(content: content))
        }

    }

    struct Card
    {
        var isFaceUp: Bool = false
        var isMatched: Bool = false
        var content: CardContent
    }
}

CodePudding user response:

It's entirely subjective, MVVM is just a design pattern and does not need to be rigorously adhered to.

Note that in MVVM a given view is typically "backed" by a single ViewModel and that a VM might interact with many different models. If the data is to be shared across views, it probably belongs on some shared model. If the data just used on a single view, it's likely fine on the VM.

CodePudding user response:

I knew and understood which lecture you are referring too.

Model is for storing the data, but VM is the middleman who can uses the Model to compute data or update the View without giving the View a direct access to the Model. ViewModel also updates the Model whenever it receives any specific interaction from the View or User. You do not process or compute any data inside a Model to update the View. You must use the ViewModel.

Also, in this case the "emojis" array is not really the main model. It is just an array of String not "Card". emojis is used to store the data for initializing the "Model". Think of it like an input from the user, you need this to pass to your Model, otherwise you don't need a Model if you don't have any data to store or initialize.

The main model is still "Card", and "Card" is still completely abstract in this context.

ViewModel's job is to compute the data like a middleman and then either passing it to the Model or Update the View. Also, it is fully possible for a ViewModel to have its own implemented variables for helping the process between VM and Model or VM and View.

All in all, Model does not do any process, compute, direct interact with the View. Model only stores the data. ViewModel does all the compute, process, initialize.

CodePudding user response:

ViewModel is a common incorrect interpretation of the underlying concept, stemming from the lack of spaces that we have in programming languages obfuscating intent. What you’re actually working with is a View Model, expressible in Swift via View.Model or Model.View

struct CardView: View {
  struct Model: DynamicProperty {
extension MemoryGame.Card {
  struct View: SwiftUI.View

…or, when it’s a model for several views instead of one, that’s called a Store:

final class Store: ObservableObject {

Even though MVVM is a cross-platform term that Apple has largely rejected, every view has a model, regardless of if you abstract it into a separate type. The view model is anything the view needs to draw itself. Anything outside of that is a model for something else and doesn’t belong in the type.

  • Related