www.youtube.com/watch?v=SIYdYpPXil4&list=PLpGHT1n4-mAtTj9oywMWoBx0dCGd51_yG&index=3
소스
MemoryGame.swift
//
// MemoryGame.swift
// Memorize
//
// Created by user on 2021/01/16.
//
import Foundation
struct MemoryGame<CardContent> {
var cards: Array<Card>
mutating func choose (card: Card){
print("card chosen: \(card)")
let choseIndex: Int = index(of: card)
cards[choseIndex].isFaceUp = !cards[choseIndex].isFaceUp
}
func index(of card: Card) -> Int {
for index in 0..<cards.count {
if cards[index].id == card.id {
return index
}
}
return 0
}
init (numberOfPairsOfCards: Int, cardContentFactory: (Int)-> CardContent) {
cards = Array<Card>()
for pairIndex in 0 ..< numberOfPairsOfCards {
let content = cardContentFactory(pairIndex)
cards.append(Card(content: content, id: pairIndex * 2))
cards.append(Card(content: content, id: pairIndex * 2 + 1 ))
}
}
struct Card: Identifiable {
var isFaceUp: Bool = true
var isMatched: Bool = false
var content: CardContent
var id: Int
}
}
EmojiMemoryGame.swift
//
// EmojiMemoryGame.swift
// Memorize
//
// Created by user on 2021/01/16.
//
import SwiftUI
class EmojiMemoryGame: ObservableObject {
@Published private var model: MemoryGame<String> = EmojiMemoryGame.createMemoryGame()
static func createMemoryGame() -> MemoryGame<String>{
let emojis: Array<String> = ["😊", "😱", "😎"]
return MemoryGame<String>(numberOfPairsOfCards: emojis.count) { parIndex in
return emojis[parIndex]
}
}
// MARK: - Access to the Model
var cards: Array<MemoryGame<String>.Card> {
model.cards
}
// MARK: - Intent(s)
func choose(card: MemoryGame<String>.Card){
model.choose(card: card)
}
}
- ObservableObject는 Protocol으로 Combine 프레임워크의 일부다.
- 이것을 사용하기 위해서는, Protocol을 준수하고 @Published를 사용하면 된다.
- @Published를 사용하면 변수의 값이 추가되거나 삭제 되었다는 것을 View가 알 수 있게 해준다.
- ObservableObject는 MVVM 아키텍쳐의 ViewModel에 적용하기 좋은 프로토콜이다.
ContentView.swift
//
// ContentView.swift
// Memorize
//
// Created by user on 2021/01/15.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel: EmojiMemoryGame
var body: some View {
HStack{
ForEach(viewModel.cards) { card in
CardView(card: card).onTapGesture {
viewModel.choose(card: card)
}
}
}
.padding()
.foregroundColor(Color.orange)
}
}
struct CardView: View {
var card: MemoryGame<String>.Card
var body: some View {
// GeometryReader는 SwiftUI 에서 View가 포함된 부모뷰(컨테이너)의
// 크기를 기준으로 View의 frame 조절하는 방법
GeometryReader(content: { geometry in
ZStack {
if card.isFaceUp {
RoundedRectangle(cornerRadius: conrnerRadius)
.fill(Color.white)
RoundedRectangle(cornerRadius: conrnerRadius)
.stroke(lineWidth: edgeLineWidth)
Text(card.content)
} else {
RoundedRectangle(cornerRadius: conrnerRadius)
.fill()
}
}
.font(Font.system(size: fontSize(for: geometry.size)))
})
}
// MARK: - Drawing Constants
let conrnerRadius: CGFloat = 10
let edgeLineWidth: CGFloat = 3
func fontSize(for size: CGSize) -> CGFloat {
min(size.width, size.height) * 0.75
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(viewModel: EmojiMemoryGame())
}
}
- View에는 Model을 Binding하여 View를 다시 그리게 하는 @ObservedObject를 이용
프로토콜(Protocol)
특정 작업이나 기능의 조각에 맞게 메서드, 속성 및 기타 요구 사항 정의
요구 사항의 실제 구현을 제공하기 위해 클래스, 구조 또는 열거에서 프로토콜을 채택
확장(Extension)
기존 유형을 확장하여 새 프로토콜을 채택하고 준수
확장은 기존 유형에 새 속성, 메서드 및 첨자를 추가 할 수 있으므로 프로토콜이 요구
docs.swift.org/swift-book/LanguageGuide/Protocols.html
Protocols — The Swift Programming Language (Swift 5.3)
Protocols A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of tho
docs.swift.org
'IOS' 카테고리의 다른 글
3. IOS 강의 Animation (0) | 2021.01.18 |
---|---|
3. IOS 강의 ViewBuilder Shape ViewModifier (0) | 2021.01.18 |
3. IOS 강의 Grid enum Optionals (0) | 2021.01.18 |
3. IOS 강의 MVVM and the Swift Type System (0) | 2021.01.17 |
3. IOS 강의 Course Logistics and Introduction to SwiftUI (0) | 2021.01.15 |