美文网首页
2021-09-18

2021-09-18

作者: 脑子 | 来源:发表于2021-09-18 00:37 被阅读0次

    MemorizeApp.swift

    import SwiftUI
    
    @main
    struct MemorizeApp: App {
        let game = EmojiMemoryGame()
        
        var body: some Scene {
            WindowGroup {
                ContentView(viewModel: game)
            }
        }
    }
    //struct MemorizeApp: App {
    //    //用let,因为EmojiMemoryGame()是个class,这里是一个引用类型,game就是一个指针,let game意思是我不会改变这个指针,但他指向哪我是会改变的,游戏会变,但路径不变。
    //    //viewmodel EmojiMemoryGame可以通过指针更改
    //    //创建一个EmojiMemoryGame()开闭括号因为类获得了免费的init,EmojiMemoryGame是个class,调用它获得一个什么都不做的init,里面只有一个变量获取免费的init。
    //    //我们正在用那个免费的init来创建表情符号游戏
    //    //MARK:3,搞个viewmodel,为的是给下面的ContentView的变量viewModel赋值
    //    let game = EmojiMemoryGame()
    //    var body: some Scene {
    //        WindowGroup {
    //            //给ContentView的变量viewModel赋值
    //            //把名字为game的viewModel传给ContentView,viewModel的类型是EmojiMemoryGame,EmojiMemoryGame是个class,是引用类型的,传递指针
    //            ContentView(viewModel: game)
    //        }
    //    }
    //}
    
    

    ContentView.swift

    import SwiftUI
    
    
    struct ContentView: View {
        @ObservedObject var viewModel: EmojiMemoryGame
        @State var emojiCount = 4
        
        var body: some View {
            VStack {
                ScrollView {
                    LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]){
                        ForEach(viewModel.cards) { card in
                            CardView(card: card)
                                .aspectRatio(2/3, contentMode: .fit)
                                .onTapGesture {
                                    viewModel.choose(card)
                                }
                        }
                    }
                }
                .foregroundColor(.red)
                Spacer()
                
            }
            .padding(.horizontal)
            
        }
    }
    
    struct CardView: View {
        let card: MemoryGame<String>.Card
        
        var body: some View {
            ZStack {
                let shape = RoundedRectangle(cornerRadius: 20)
                if card.isFaceUp {
                    shape.fill().foregroundColor(.white)
                    shape.strokeBorder(lineWidth: 3)
                    Text(card.content).font(.largeTitle)
                    
                } else {
                    shape.fill()
                }
            }
        }
    }
    
    
    
    
    
    
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            let game = EmojiMemoryGame()
            ContentView(viewModel: game)
                .preferredColorScheme(/*@START_MENU_TOKEN@*/.dark/*@END_MENU_TOKEN@*/)
            ContentView(viewModel: game)
                .preferredColorScheme(.light)
        }
    }
    
    
    //struct ContentView: View {
    //    var emojis = ["🚙", "🚗", "⛱", "🎡", "🪝", "🗿", "🛖", "⏱", "☎️", "🎰","🚜","🛴", "✈️"]
    //    @State var emojiCount = 4
    //
    //    var body: some View {
    //        VStack {
    //            ScrollView {
    //                LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]){
    //                    ForEach(emojis[0..<emojiCount], id: \.self) { emoji in
    //                        CardView(content: emoji).aspectRatio(2/3, contentMode: .fit)
    //                    }
    //                }
    //            }
    //            .foregroundColor(.red)
    //            Spacer()
    //            HStack {
    //                remove
    //                Spacer()
    //                add
    //            }
    //            .font(.largeTitle)
    //            .padding(.horizontal)
    //        }
    //        .padding(.horizontal)
    //
    //    }
    //    var remove: some View {
    //        Button(action:{
    //            if emojiCount > 1{
    //                emojiCount -= 1
    //            }
    //        }, label: {
    //            Image(systemName: "minus.circle")
    //        })
    //    }
    //    var add: some View {
    //        Button(action:{
    //            if emojiCount < emojis.count {
    //                emojiCount += 1
    //            }
    //        }, label: {
    //            Image(systemName: "plus.circle")
    //        })
    //    }
    //}
    //
    //struct CardView: View {
    //    var content: String
    //    @State var isFaceUp: Bool = true
    //
    //    var body: some View {
    //        ZStack {
    //            let shape = RoundedRectangle(cornerRadius: 20)
    //            if isFaceUp {
    //                shape.fill().foregroundColor(.white)
    //                shape.strokeBorder(lineWidth: 3)
    //                Text(content).font(.largeTitle)
    //
    //            } else {
    //                shape.fill()
    //            }
    //        }
    //        .onTapGesture {
    //            isFaceUp = !isFaceUp
    //        }
    //    }
    //}
    
    
    //struct ContentView: View {
    //    //这是用viewModel浏览卡片
    //    //MARK:26,@ObservedObject意思是当viewModel有变化时,重建整个body
    //    //MARK: 1,把View和viewModel链接:ContentView必须能看到model,它才能绘制model的UI
    //    //MARK: 2,因为ContentView多了一个变量viewModel,需要把用到ContentView的地方把变量viewModel都赋值
    //    //MARK: 8,把var改成let
    //    @ObservedObject var viewModel: EmojiMemoryGame
    //    //var viewModel: EmojiMemoryGame, ContentView通过EmojiMemoryGame来显示,现在只用让var body工作来展示
    //    //var声明变量,body是变量的名字,some View是变量的类型.{}内的是个没有名字的函数,隐藏了return,返回一个Text
    //    //content 最后一个参数,可以从括号里删除,{}里的是ZStack的content参数
    //    //用ForEach创造数组中每个事物的CardView,content是我们的CardView,ForEach需要数组emojis,有content这个内容参数,在hstack中的视图组合器,ForEach本身不是视图组合器,是乐高制造商,他让一袋乐高装满了东西。提供为数组中的每个东西做点事情。
    //    //给函数{}加参数{参数名1, 参数名2, in};CardView(content: emoji)为每个CardView指定emoji;
    //    //id: \.self 用结构体本身做唯一标识符
    ////    var emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
    ////
    ////    @State var emojiCount = 14
    //
    //    //var body:给我个uI让我看看model里有什么
    //    var body: some View {
    //
    //            ScrollView{
    //                //LazyVGrid会制作许多列,不能放数字,要放GridItem数组,GridItem可以控制列,GridItem(.fixed(200))第一个列有200宽度
    //                //LazyVGrid水平使用所有宽度,垂直尽可能小以便多放东西。LazyVGrid的Lazy意思是不滚动不加载
    //                //.adaptive(minimum: 65)最小宽度65
    //                LazyVGrid(columns: [GridItem(.adaptive(minimum: 65))]){
    //                    //让ForEach认为string是可识别的,id: \.self
    //                    //emoji是这个函数的参数,用in将它分开,从执行的代码返回CardView
    //
    //                    //MARK:5,因为有了viewmodel,所以视图要现实viewmodel中的东西
    //                    //ForEach(emojis[0..<emojiCount], id: \.self){ emoji in
    //                    //出错是因为cards不可识别?卡片数组必须Identifiable
    //
    //                    //如果viewModel中是private(set) var model,下面的var cards:注释掉没有,则ForEach(viewModel.model.cards)
    //                    //MARK:6,把emoji in 改成card in
    //                    ForEach(viewModel.cards){ card in
    //
    //                        //用ForEach遍历viewModel中的所有卡片,cards是viewmodel中的var cards: Array<MemoryGame<String>.Card>,model.cards是个数组。ForEach遍历出每一张卡片,要给它做个CardView视图展示
    //                        //人们创建struct时会设置值
    //                        //MARK:9,CardView(content: emoji)改为CardView(card: card)
    //                        //CardView是单个卡片视图
    //                        CardView(card: card)
    //                            .aspectRatio(2/3, contentMode: .fit)
    //
    //                            //MARK: - intent(s)添加注释
    //                            //intent都记录在ViewModel中,通过它来表达用户意图
    //                            //MARK:12, .onTapGesture 给卡片添加翻面功能
    //                            .onTapGesture {
    //                                viewModel.choose(card)
    //                            }
    //                    }
    //                }
    //            }
    //
    //            .foregroundColor(.red)
    //            //Spacer占有其他人不要的所有空间
    ////            Spacer()
    ////            HStack{
    ////                add
    ////                Spacer()
    ////                remove
    ////            }
    ////            .font(.largeTitle)
    ////            .padding(.horizontal)
    //
    //
    //        .padding(.horizontal)
    //
    //    }
    //
    ////加减卡片
    ////    var remove: some View {
    ////        Button {
    ////            if emojiCount > 1 {
    ////                emojiCount -= 1
    ////            }
    ////        } label: {
    ////           Image(systemName: "minus.circle")
    ////        }
    ////    }
    ////    var add: some View {
    ////        Button {
    ////            if emojiCount < emojis.count{
    ////                emojiCount += 1
    ////            }
    ////        } label: {
    ////            Image(systemName: "plus.circle")
    ////
    ////        }
    ////    }
    //
    //
    //}
    //
    ////CardView单个卡片视图,@State重建视图,指针不变;content是卡片的内容
    ////CardView正在显示这张卡片,为这张卡构建一个UI
    //struct CardView: View {
    //    //MARK:7,在这个CardView创建card并且为他建立一个body,只传一张卡
    //    //MARK:7-1,强烈推荐:这里没有将整个model传给他,只传model的一部分,当你构建一个view时,只传人他完成工作所需的最低限度的model,CardView的工作是为我构建一个显示卡片的UI在model中,只把卡传给他。这里用let,因为卡片视图不会改变
    //    //@State在视图中非常罕见,所以你视图中不会有很多变量。
    //    let card: MemoryGame<String>.Card
    //    //struct中变量可以没有初始值
    ////    var content: String
    ////   @State var isFaceUp: Bool = true
    //
    //    var body: some View {
    //        ZStack{
    //            let shape = RoundedRectangle(cornerRadius: 20)
    //            //MARK:10,if isFaceUp 改成if card.isFaceUp,Text(card.content)
    //            if card.isFaceUp {
    //                //stroke边缘 fill默认填充
    //                shape.fill().foregroundColor(/*@START_MENU_TOKEN@*/.white/*@END_MENU_TOKEN@*/)
    //                //strokeBorder笔划边框
    //                shape.strokeBorder(lineWidth: 3)
    //                Text(card.content).font(.largeTitle)
    //            } else {
    //                shape.fill()
    //            }
    //
    //        }
    ////反转卡片
    ////        .onTapGesture {
    ////            isFaceUp = !isFaceUp
    ////        }
    //
    //    }
    //}
    //
    //struct ContentView_Previews: PreviewProvider {
    //    static var previews: some View {
    //        //MARK:4,给用到ContentView地方的变量赋值,game是个指针,创造一个游戏,把它传递给viewModel的明暗两个视图
    //        let game = EmojiMemoryGame()
    //        //ContentView()
    //        ContentView(viewModel: game)
    //            .preferredColorScheme(.dark)
    //        ContentView(viewModel: game)
    //            .preferredColorScheme(.light)
    //
    //
    //
    //    }
    //}
    
    

    MemoryGame.swift

    //Foundation是个数组,字符串,字典组成的基础包,不是按钮或视图api
    //前变量后值或类型
    import Foundation
    
    struct MemoryGame<Content> {
        private(set) var cards: Array<Card>
        
        mutating func choose(_ card: Card){
            let chosenIndex = index(of: card)
            cards[chosenIndex].isFaceUp.toggle()
     //print("chosenCard = \(chosenCard)")
            print("\(cards)")
        }
        
        func index(of card: Card) -> Int {
            for index in 0..<cards.count {
                if cards[index].id == card.id {
                return index
                }
            }
            return 0
        }
        
        init(numberOfPairOfCards: Int,createCardContent:(Int) ->Content ) {
            cards = Array<Card>()
            for pairIndex in 0..<numberOfPairOfCards{
                let content: Content = createCardContent(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: Content
            var id: Int
        }
    }
    //
    //struct MemoryGame<CardContent> {
    //    private(set) var cards: Array<Card>
    //
    //    //MARK:19 mutating放在func前面告诉全世界调用这个函数将改变整个struct,所以这个函数只能在MemoryGame作为变量var的地方调用
    //    //MARK:21,所以说这个函数可变,可以改变整个struct
    //    mutating func choose(_ card: Card) {
    //
    //        //card.isFaceUp.toggle()//函数里的参数是常数,会报错
    //        //MARK:13,编写一个名为index(of: )的函数,这张卡片的索引的函数,在array中找到这张卡片
    //        let chosenIndex = index(of: card)
    //        //MARK:15,
    ////        var chosenCard = cards[chosenIndex]
    ////        chosenCard.isFaceUp.toggle()
    //        //MARK:18
    //        cards[chosenIndex].isFaceUp.toggle()
    //        //MARK:16,
    //        //print("chosenCard = \(chosenCard)")
    //        print("\(cards)")
    //    }
    //
    //    //MARK:14, 实现上面的函数index(of: card),卡片的索引,这是该数组的索引
    //    func index(of card: Card) -> Int {
    //        // MARK:17,如果卡片索引的ID==卡片ID,返回int类型的index
    //        for index in 0..<cards.count {
    //            if cards[index].id == card.id {
    //                return index
    //            }
    //        }
    //        return 0 //bogus!
    //    }
    //
    //    init(numberOfPairOfCards: Int, creatCardContent:(Int) -> CardContent) {
    //        cards = Array<Card>()
    //        for pairIndex in 0..<numberOfPairOfCards{
    //            let content: CardContent = creatCardContent(pairIndex)
    //            //MARK:11,给卡片组加ID参数
    //            cards.append(Card(content: content, id: pairIndex*2))
    //            cards.append(Card(content: content, id: pairIndex*2+1))
    //        }
    //    }
    //
    //    //MARK:10-1,让卡片可识别Identifiable
    //    struct Card:Identifiable {
    //        var isFaceUp: Bool = false
    //        var isMatched: Bool = false
    //        var content: CardContent
    //        var id: Int
    //    }
    //
    //}
    //----------------------------------------------------------
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //struct MemoryGame<CardContent> {
    //    private(set) var cards: Array<Card>
    //
    //    //mutating 这个函数可以改变整个struct
    //    mutating func choose(_ card: Card){
    //        //card.isFaceUp.toggle()
    //        //编写一个index(of:)的函数
    //        let chosenIndex = index(of: card)
    //        cards[chosenIndex].isFaceUp.toggle()
    //        print("\(cards)")
    //    }
    //
    //    func index(of card: Card) -> Int {
    //        for index in 0..<cards.count {
    //            if cards[index].id == card.id {
    //                return index
    //            }
    //        }
    //        return 0
    //    }
    //
    //    init(numberOfPairOfCards: Int, createCardContent:(Int) ->CardContent) {
    //        cards = Array<MemoryGame.Card>()
    //        for pairIndex in 0..<numberOfPairOfCards{
    //
    //            let content: CardContent = createCardContent(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
    //    }
    //}
    //
    //
    //
    
    
    
    
    
    ////model是个简单的MemoryGame模型
    ////我们使用范型<CardContent> 必须向全世界宣布,放在<>里,
    ////当有人用我们的MemoryGame时,他们将不得不告诉我们这个范型是什么,不能一直don’t care,我们不关心,但谁用谁关心。我们做表情游戏时,它将成为一个String
    //struct MemoryGame<CardContent> {
    //    //有卡片:放在数组里<卡片阵列>
    //    //Model保护其卡片免受ViewModel的影响,只看不动
    //    //这个cards:Array<Card>在使用前要先用下面的init进行初始化
    //    //var cards: Array<Card> 由Card类型组成的数组
    //    private(set) var cards: Array<Card>
    //
    //    //有选择卡片
    //    func choose(_ card: Card) {
    //
    //    }
    //
    //    //init初始化未设置的变量,numberOfPairsOfCards初始化的时候你得知道有几对卡,一共有10对卡,创建第一对卡的内容,返回第一对卡的内容。
    //    init(numberOfPairsOfCards: Int, createCardContent: (Int) -> CardContent) {
    //        //创建空的<卡片阵列>,初始化了一个空的卡片数组,所以上面能用
    //        cards = Array<Card>()
    //        //add numberOfPairsOfCards x 2 cards to cards array,卡的对数乘以2就是有多少卡,(for 第几对 in 对数)
    //        for pairIndex in 0..<numberOfPairsOfCards {
    //            //制作一对卡,cards.append(Card(isFaceUp: false, isMatched: false, content: <#T##CardContent#>)),因为struct Card中有默认值,所以isFaceUp: false, isMatched: false不需要了
    //            //创建一个函数createCardContent,把pairIndex传给它,createCardContent这个函数从哪来?
    //            //let content: CardContent = createCardContent(pairIndex) //类型推断,干掉CardContent
    //            //let 卡的内容 = 创建卡的内容(第几对)
    //            //var content: CardContent = ... 创建一个变量 它是CardContent类型的。让createCardContent这个函数来创建卡片内容
    //            //createCardContent: (Int) -> CardContent 传入要创建第几对卡的数组,比如1,返回第一对卡的内容,把函数直接写到参数里。
    //            let content = createCardContent(pairIndex)
    //            //给每张卡设置内容。(content: CardContent),CardContent是个范型,不确定它是什么类型,(content: content)前面是参数,后面值。
    //            cards.append(Card(content: content))
    //            cards.append(Card(content: content))
    //        }
    //    }
    //
    //    //MemoryGame.Card,卡片有哪些属性
    //    struct Card {
    //        var isFaceUp: Bool = false //是否正面朝上
    //        var isMatched: Bool = false //是否匹配
    //        var content: CardContent //卡片上有什么,String?可以做的更好,未来有任意图像而不是表情符号;CardContent范性--随便啥:don't care
    //    }
    //}
    
    

    EmojiMemoryGame.swift

    // #ViewModel
    
    //虽然ViewModel是我们UI的一部分,但它不是swiftUI视图,是用户界面的一部分
    //ViewModel是个中介,在Model和View之间;它需要和Model建立连接,实际上ViewModel会重建自己的Model。有时候Model是数据库
    //你玩游戏它就在那里,如果ViewModel消失了,然后游戏结束了。
    //因为很多时候ViewModel创建自己的Model,我们会经常说ViewModel是程序中的truth。Model是app的truth,如果ViewModel在创建自己的模型,则本质上ViewModel是truth
    //添加三个关键字让我们的UI变成完全反应式的UI,我们model的任何更改都会更新匹配UI
    //ObservableObject,viewmodel向世界发布something changed,model变化了,view知道viewmodel改变时重绘,@ObservedObject,
    
    import SwiftUI
    
    
    class EmojiMemoryGame: ObservableObject {
        static var emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
        
        static func makeMemoryGame() -> MemoryGame<String> {
            MemoryGame<String>(numberOfPairOfCards: 4) { pairIndex in emojis[pairIndex]}
        }
        @Published private var model: MemoryGame<String> = makeMemoryGame()
        
        var cards: Array<MemoryGame<String>.Card> {
            return model.cards
        }
        
        //MARK: - Intent(s)
        
        func choose(_ card: MemoryGame<String>.Card) {
            model.choose(card)
        }
    }
    
    //MARK:22,ObservableObject 向全世界发布“有所改变”
    //class EmojiMemoryGame: ObservableObject {
    //    static var emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
    //
    //    static func makeMemoryGame() -> MemoryGame<String> {
    //        MemoryGame<String>(numberOfPairOfCards: 4 ){ pairIndex in emojis[pairIndex]}
    //    }
    //
    //    //MARK:24,@Published 无论model发生任何变化,它都会执行objectWillChange.send()
    //    //倾向于让model完全私有,通过var和func将其暴露给view
    //    //MARK:20,如果这里为let model 则下面model.choose(card)就不能用,这就是swift的写时复制的方式,它强制事物的可变性
    //    @Published private var model: MemoryGame<String> = makeMemoryGame()
    //
    //    var cards: Array<MemoryGame<String>.Card> {
    //        model.cards
    //    }
    //
    //    //MARK:12-1,实现viewModel.choose(card)
    //    func choose(_ card: MemoryGame<String>.Card) {
    //        //MARK:23,向全世界发布objectWillChange 在model前面加上@Published
    //        //objectWillChange.send()
    //        //13,
    //        //MARK:25,choose是mutating func,所以swiftUI会自动执行objectWillChange.send()
    //        model.choose(card)
    //    }
    //}
    //-----------------------------------------------------------------
    
    
    //ObservableObject向全世界宣布有东西改变了!
    //class EmojiMemoryGame: ObservableObject {
    //    static var emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
    //    
    //    static func makeMemoryGame() -> MemoryGame<String> {
    //        MemoryGame<String>(numberOfPairOfCards: 4) { pairIndex in emojis[pairIndex] }
    //    }
    //    
    //    //让model完全私密,通过var func暴露给view
    //    //在任何变量前加关键字@Published,无论model发生任何变化,它都会自动执行objectWillChange.send()
    //    @Published private var model: MemoryGame<String> = makeMemoryGame()
    //
    //    //viewModel.cards
    //    var cards: Array<MemoryGame<String>.Card> {
    //        model.cards
    //    }
    //    
    //    // MARK: - Intent(s)
    //    //用户的意图,这个Intent是我们必须勾在UI上的东西,我们的UI会表达这个Intent
    //    //choose是个mutating func,swiftUI知道这改变了它,会自动执行objectWillChange.send()
    //    func choose(_ card: MemoryGame<String>.Card) {
    //        //向世界发布这个objectWillChange,model changed
    //        //objectWillChange.send()
    //        model.choose(card)
    //    }
    //}
    
    //
    //class EmojiMemoryGame {
    //
    //    let emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
    //
    //    private var model: MemoryGame<String> =
    //        MemoryGame<String>(numberOfPairsOfCards: 4) { pairIndex in
    //            "🚙" }
    //
    //    var cards: Array<MemoryGame<String>.Card> {
    //        return model.cards
    //    }
    //}
    
    //createCardContent: (Int) -> CardContent,createCardContent: (Int) -> String 接收int返回string
    //func makeCardContent(index: Int) -> String {
    //    return "🎳"
    //}
    
    //类可以继承
    //class EmojiMemoryGame {
    //
    //    //从视图中获取表情符号,static意味着基本上是全局的,emojis相对于EmojiMemoryGame是全局的
    //    static let emojis = ["🚝","🏍","🚖","🚀","🚕","🚎","🚑","🚜","🦽","🚔","🛸","🚂","🚞","🚨"]
    //
    //    //创建记忆游戏 类型函数
    //    static func createMemoryGame() -> MemoryGame<String> {
    //       return MemoryGame<String>(numberOfPairsOfCards: 4)  { pairIndex in
    //        emojis[pairIndex]
    //       }
    //    }
    //
    //
    //     private let model: MemoryGame<String> = createMemoryGame()
    //
    //    //我们的模型是个结构体struct,所以我们要创建一个名为model的变量var,它是MemoryGame类型的
    //    //因为MemoryGame<CardContent>是范型的,所以我们要指明CardContent是什么类型,这是一个EmojiMemoryGame,所以它是string,表情符号是字符串
    //    //ViewModel是Model的看门人,ViewModel保护model免受不良行为的影响,谁有权访问ViewModel;我们的做法是制作私有model
    //    //private意味着只有ViewModel代码本身可以看到Model,它保护Model,阻止任何访问修改;private是访问控制的一部分。
    //    //有时候完全私有有点太严格了,例如在我们的记忆游戏中人们需要看到这些卡片,否则我们的视图将怎么绘制卡片?
    //    //所以还有另外一个private(set)私有,它告诉swift其他类和struct可以查看model,但无法改变它。它不能调用func choose,因为那会改变MemoryGame,最特别是他们无法读取Card并更改isFaceup、isMatched等。
    //    //private var model: MemoryGame<String>
    //    //class中所以的变量都要有值,MemoryGame<String>(numberOfPairsOfCards: 4)设置默认4张卡
    
    ////    private var model: MemoryGame<String> = MemoryGame<String>(numberOfPairsOfCards: 4)  { pairIndex in
    ////        //pairIndex 第几对表情
    ////        //{ pairIndex in emojis[pairIndex] } = {99 in 表情数组[99]}
    ////        //不能使用带有属性初始化的实例成员,属性初始值设定项在“self”可用前运行。
    ////        //实例成员意味着在EmojiMemoryGame中的任何函数或变量,每当我建立一个EmojiMemoryGame,我会得到一个emojis和一个Model,不能像emojis使用在初始值设定项中,属性初始化器?property这个词只是指类或结构中的变量或常量属性,使用等号的属性。
    ////        //私有属性只在本文件内可用访问。
    ////        //model和emojis这两个属性初始化顺序是随机的,你在后面这个函数里emojis[pairIndex]使用它 它可能还没初始化。可以用init来初始化emojis
    ////        emojis[pairIndex]
    ////
    ////    }
    //
    //
    //    //1,model完全私有则必须有自己的cards,model.cards
    //    //2,views可以调用ViewModeel自己的var,拿到cards。
    //    //Model中的cards是个struct结构体,他们是一组卡片,我们传递struct时我们复制他们
    //    var cards: Array<MemoryGame<String>.Card> {
    //        return model.cards
    //    }
    //}
    
    

    相关文章

      网友评论

          本文标题:2021-09-18

          本文链接:https://www.haomeiwen.com/subject/ohlegltx.html