개발을 시작하는 이야기

[SwiftUI] Lecture 3: MVVM and the Swift type system 본문

개발 이야기/Swift

[SwiftUI] Lecture 3: MVVM and the Swift type system

Teiresias 2022. 4. 12. 18:25

강의 보기 : Youtube :: Stanford 

 

MVC : UIKit 기반의 디자인 패턴

MVVM : SwiftUI를 위한 디자인 패턴

 

각각의 디자인 패턴에 대한 설명은 일전에 작성해둔 글의 링크로 대체한다.

 

Struct와 Class 

Struct Class
Value type Reference type
Copied when passed or assigned Passed around via pointers
Copy on write Automatically reference counted
Functionak programming Object-oriented programming
No inheritance Inheritance (single)
"Free" init initializes All vars "Free" init initalizes No vars
Multability must be explicitly stated Always mutable
Your "go to" data structure Used in specific circumstances
Everything you've seen so far is a struct
(except View which is a protocol)
The ViewModel in MVVM is always a class
(also, UIK (old style iOS) is class-based)

Generics

제네릭이란 타입에 의존하지 않는 범용 코드를 작성할 때 사용한다.

제네릭을 사용하면 중복을 피하고, 코드를 유연하게 작성할 수 있다.

Swift에서 가장 강력한 기능 중 하나로 Swift 표준 라이브러리의 대다수는 제네릭으로 선언되어 있다고 한다. 

 

꺾새(<>)를 이용해서 안에 타입처럼 사용할 이름을 선언해주면 해당 이름을 타입처럼 사용할 수 있다. 여기서 선언한 이름을 Type Parameters라고 하는데, 새로운 형식이 생성되는 것이 아닌, 실제 함수가 호출될 때 해당 매개변수 타입으로 대체되는 Placeholder라고 볼 수 있다. 


기존의 프로젝트에서 Model과 ViewModel을 분리시켜주었다.

Model

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: CardContent = 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
    }
}

ViewModel

import SwiftUI

class EmojiMemoryGame {
    static let emojis = ["💡", "📋", "🖥", "😺", "🗺", "😱", "🙈", "🤔", "📪", "👨‍🏫", "📱", "🎉", "📄", "💁", "📞", "👨‍💻", "⚒", "🙋", "🤵‍♂️", "😀", "😃", "😄", "😁"]
    
    static func createMemoryGame() -> MemoryGame<String> {
        MemoryGame<String>(numberOfPairsOfCards: 4) { pairIndex in
            emojis[pairIndex]
        }
    }
    
    private var model: MemoryGame<String> = createMemoryGame()
    
    var cards: Array<MemoryGame<String>.Card> {
        return model.cards
    }
}

static

Type Property를 사용하기 위해 저장, 연산 프로퍼티 앞에 'static'을 붙여서 사용한다. (class 키워드도 사용하긴 한다) 저장 타입 프로퍼티의 경우 선언할 당시 원하는 값으로 항상 초기화가 되어 있어야 한다. 'static'을 이용해 선언하며, 자동으로 lazy로 작동한다. (lazy를 직접 붙일 필요 또한 없다.)

 


참고자료 : Generics , static,