SwiftUI - Stanford Lecture 3-2 : MVVM and the Swift type system

SeBin·2023년 5월 19일
0

SwiftUI Stanford

목록 보기
4/4
post-thumbnail

Upgrade Memorize Prototype Code

이전에 작성한 Memorize 게임의 Prototype을 실제 MVVM 패턴에 알맞게 동작하도록 개선해보자

Model

Model은 SwiftUI를 사용하지 않기 때문에 Swift파일로 새로 만든다.

import Foundation

struct MemoryGame<CardContent> {
    private(set) var cards: Array<Card>
    
    func choose(_ card: Card) {
        
    }
    
    init(numberOfPairsOfCards: Int, createCardContent: (Int) -> CardContent) {
        cards = Array<Card>()
        // add numberOfPairsOfCards x 2 cards to cards array
        for pairIndex in 0..<numberOfPairsOfCards {
            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
    }
}

구조체 안에 구조체를 정의함으로써 좋은점 : Namespace를 지정할 수 있어서 만약 다른 카드 게임이 존재해도 MemoryGame.Card로 접근하여 쉽게 구분할 수 있다.

카드 구조체의 content는 String이 들어가던 이미지가 들어가던 어떤 데이터 타입이 들어와도 상관없게끔 generics을 활용하여 정의한다.

모든 변수에는 반드시 값이 할당되어 있어야 하므로 생성자를 정의하여 값을 초기화해야 한다. 이러한 initalizer를 선언할 수 있게 하는 init 함수가 있다.

ViewModel

ViewModel은 Model과 View 사이의 중개자이며 반드시 Model과 연결되어 있어야 한다. 또한 디스크나 네트워크와 같은 것들의 항목을 유지하도록 돕는 일도 수행한다.

특히 Model에서 View로 이어지는 문지기(Gatekeeper)역할을 한다.
악의적인 행위를 하는 View나 다른 프로그래머로부터 Model을 지키기 위함이다.

import SwiftUI

class EmogiMemoryGame {
   static var emojis = ["🚗", "🚕", "🚙", "🚌", "🚎", "🏎️", "🚓", "🚑", "🚒", "🛻", "🚚", "🚛", "🚜", "🛵", "🏍️", "🛺", "🚠", "🚡", "🚟", "🚃", "🚋", "🚞", "🚝", "🚄", "🚅", "🚈", "🚂", "⛵️", "🚤"]
    
    static func createMemoryGame() -> MemoryGame<String> {
        MemoryGame<String>(numberOfPairsOfCards: 4) {pairIndex in EmogiMemoryGame.emojis[pairIndex]
        }
    }
    
    private var model: MemoryGame<String> = EmogiMemoryGame.createMemoryGame()
    
    var cards: Array<MemoryGame<String>.Card> {
        return model.cards
    }
}

private를 활용해 읽고 쓰는 것 둘 다 제한시킬 수 있다. private(set)을 활용하면 읽을 수는 있지만 쓰지 못하게 제한 할 수도 있다.

static은 emoji 배열을 전역 변수처럼 사용할 수 있게 한다. 동시에 EmogiMemoryGame이라는 namespace에 가둠으로써 변수가 겹치지 않게 한다.

EmojiMemoryGame.emojis[pairIndex]

static은 Attribute 뿐만 아니라 함수에도 사용할 수 있다. 그래서 EmogiMemoryGame에 종속된 함수 또는 변수임을 강조할 수 있다.

0개의 댓글