見出し画像

SwiftUIでいこう!- スタンフォード大学Lecture 3: MVVM

神経衰弱ゲームを構造を考えながら組み上げていきます。

Model, ViewModel , Viewの3つの構造を作って機能させます。MVVMについては以下のサイトがわかりやすく紹介されています。

このゲームをMVVMで組み上げます。まずViewの役割を持つCntentView()以外の基本的部品を見ていきましょう。

基本の構造

//Model

modelは部品の構造を書き出していきます。今後、この部品を使って画面の表示部分を作っていきます。

import Foundation

struct Game<CardContent>{
   var cards:Array<Card>
   
   func choose(card:Card){
       
   }

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

//ViewwModel

modelの部品を使って画面を構成する具体的なも機能をつけていきます。

import SwiftUI

class EmojiGame{
   
   private var model:Game<String>
           
   var cards:Array<Game<String>.Card>{
       return model.cards
   }
}

これらをもとにContentViewで表示するゲームをコントロールできるようにしていきます。

組み立て

実際に使えるようにしていきます。

Modelの"struct Game<CardContent>{}"を使えるように初期化をまず実行できるようにします。init()します

 init(numberOfpairOfCards:Int,createCardContent:(Int)->CardContent){
       cards = Array<Card>()
       for pairIndex in 0..<numberOfpairOfCards{
          //処理
       }
   }ひ

初期化では引数を2つ入れたものを作ります。カードの枚数と中に入れる絵文字を指定しています。

numberOfpairOfCards:Int, createCardContent:(Int)->CardContent

必要な枚数のカードにそれぞれ絵文字をfor 文で入れていきます。

 init(numberOfpairOfCards:Int,createCardContent:(Int)->CardContent){
       cards = Array<Card>()
      
       for pairIndex in 0..<numberOfpairOfCards{
           let content = createCardContent(pairIndex)
           cards.append(Card(content: content))
           cards.append(Card(content: content))
       }
   }
cards = Array<Card>()

に追加していきます。神経衰弱にはカードが2枚必要なので、2枚ずつ入れる仕組みを作ります。この時Cardの初期化については以下。

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

として、"init()"する前に初期化しています。("init()"の引数を"content"のみにしてシンプルに)

参考
以下のContentView()の部分で"content"の部分にデータを入れて使えるように作り込みです。
  ForEach(emojis[0..<emojicount], id: \.self){emoji in
              CardView(content:emoji).aspectRatio(2/3,contentMode:.fit)
   }


init()で初期化のコードを書いてViewModelにある

 private var model:Game<String>

の部分が書けるようになります。初期化に必要なものはカードの数と絵文字の種類となっています。

"model"での初期化は"必要な数字""第一引数を使った関数"となっているので、

let emojis = ["✈️","🐶","🐱","🐻","🚁","🚗","🚇","🚴‍♀️","🍎","🍌","🍍","🍇","🐢","🐸"]

func createMemoryGame() -> Game<String>{
       Game<String>(numberOfpairOfCards:4){pairIndex in
           EmojiGame.emojis[pairIndex]
       }
   }

createMemoryGame()として初期化します。この関数を

var model:Game<String>

に代入します。

 private var model:Game<String> = createMemoryGame()

ここの処理は

class EmojiGame{}

の中で定義されているので使うのを限定するためのコードを書きます

 static let emojis = ["✈️","🐶","🐱","🐻","🚁","🚗","🚇","🚴‍♀️","🍎","🍌","🍍","🍇","🐢","🐸"]
   
 static func createMemoryGame() -> Game<String>{
       Game<String>(numberOfpairOfCards:4){pairIndex in
           EmojiGame.emojis[pairIndex]
       }
   }

二つのコードに共通な

static

をつけます。これがないとエラーとなります。

最終的なコードはこんな感じになります。

//Model

import Foundation

struct Game<CardContent>{
  private(set) var cards:Array<Card>
   
   func choose(card:Card){
       
   }
   
   init(numberOfpairOfCards:Int,createCardContent:(Int)->CardContent){
       cards = Array<Card>()
       for pairIndex in 0..<numberOfpairOfCards{
           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
   }
   
}

//ViewwModel

import SwiftUI

class EmojiGame{
   
   static let emojis = ["✈️","🐶","🐱","🐻","🚁","🚗","🚇","🚴‍♀️","🍎","🍌","🍍","🍇","🐢","🐸"]
   
   static func createMemoryGame() -> Game<String>{
       Game<String>(numberOfpairOfCards:4){pairIndex in
           EmojiGame.emojis[pairIndex]
           
       }
   }
   
   private var model:Game<String> = createMemoryGame()
           
   
   var cards:Array<Game<String>.Card>{
       return model.cards
   }
}


この記事が気に入ったらサポートをしてみませんか?