CS193P SwiftUI 2020任务3-作为函数参数的闭包

CS193P SwiftUI 2020任务3-作为函数参数的闭包,swift,mvvm,swiftui,closures,Swift,Mvvm,Swiftui,Closures,我正在学习Paul Hegarty的CS193P 2020课程,作业3要求我们使用闭包作为函数的参数。这是我们在上一节课中已经做过的事情,对我来说很清楚(事实上我认为是的)。 在我自己尝试之后,我终于在这里找到了解决方案:它工作得很好,但我仍然很难理解发生了什么 下面是SetGame init使用闭包创建CardContent的模型代码 struct SetGame { var deck: [Card] init(cardContentFactory: (Int, Ca

我正在学习Paul Hegarty的CS193P 2020课程,作业3要求我们使用闭包作为函数的参数。这是我们在上一节课中已经做过的事情,对我来说很清楚(事实上我认为是的)。 在我自己尝试之后,我终于在这里找到了解决方案:它工作得很好,但我仍然很难理解发生了什么

下面是SetGame init使用闭包创建CardContent的模型代码

struct SetGame {
    var deck: [Card]
    
    init(cardContentFactory: (Int, CardShape, CardShading, CardColor) -> CardContent) {
        deck = [Card]()
        for number in 1...3 {
            for shape in CardShape.allCases {
                for shading in CardShading.allCases {
                    for color in CardColor.allCases {
                        let content = cardContentFactory(number, shape, shading, color)
                        deck.append(Card(id: deck.count, content: content))
                    }
                }
            }
        }
    }
}
在ViewModel中:

class SetGameViewModel: ObservableObject {
    private var setModel: SetGame
    
    init() {
        setModel = SetGame() {
            CardContent(number: $0, shape: $1, shading: $2, color: $3)
        }
        print(setModel.deck)
    }
}
关于此代码,我有两个问题:

  • 我不明白这行
    CardContent(数字:$0,形状:$1,阴影:$2,颜色:$3)
    是如何工作的,因为在我看来它似乎没有传递任何“实际”数据。在上一节课中,保罗使用的例子是传输真实数据。下面是使用的代码,它清楚地传递了冲浪者表情符号

     func createMemoryGame() -> MemoryGame<String> {
     return MemoryGame<String>(numberOfPairsOfCards: 2) { _ in "
            setModel = SetGame() {
            CardContent(number: $0, shape: $1, shading: $2, color: $3)
        }
    
    func createMemoryGame()->MemoryGame{
    返回存储器名称(卡的对数:2){in“
    这里我们使用一个尾随闭包。相反,您可以将其编写为:

    func changeThings(how f: (String) -> String) -> [String] {
        let things: [String] = ["A", "B", "C", "D"]
    
        var result: [String] = []
        for thing in things {
            result.append(f(thing))
        }
        return result
    }
    
    let lc1 = changeThings(how: { string in return string.lowercased() })
    let lc2 = changeThings(how: { $0.lowercased() })
    
    func doubleString(_ s: String) -> String {
        return "\(s)\(s)"
    }
    
    let db1 = changeThings(how: doubleString(_:))
    let db2 = changeThings(how: { "\($0)\($0)" })
    
    因此,我们将数据传递给SetGame.init(cardContentFactory:)方法:我们将传递一个闭包,该闭包稍后接受4个参数的值

    < <代码> > 0美元<代码>代码> 1美元<代码>代码> 2美元<代码>这些表示代词,对函数的参数。这些有用的原因是简明的:例如,考虑这个游戏场地:


    在这里,
    {string in return string.lowercased()}
    是一个很长的说法“lowercase it”,因此
    $0
    表示“it”。$1、$2等表示第二个、第三个参数。同样,必须创建和命名函数(如
    doubleString(:)
    也是使用匿名(未命名)的很长一段路闭包。

    据我所知,我们可以通过闭包直接传递值,或者稍后使用$x来管理值?您传递的是一个函数,也称为闭包,进入SetGame.init(cardContentFactory:)方法创建一个新的SetGame,并将此函数烘焙到其中。现在,每当SetGame想要制作一张新卡时,它都会使用此函数制作该卡的内容。$0、$1等表示在调用函数制作新卡时从SetGame传递到“卡内容工厂”函数的值此函数on是SetGame的一个参数,所以你可以修改它。你可以传入一些其他函数来制作一种不同的SetGame,它仍然使用SetGame的相同逻辑,但制作的卡片内容不同。每当它制作卡片时,非常感谢你的回答,这对我来说是有意义的。这是一大步,因为它是基础Swift.in的所有方面。在第二组代码中,
    忽略返回到闭包中的数据。将下划线替换为
    ,如果将其全部删除,您现在可以读取它。您可以使用
    $0
    读取它。$0,$1等是顺序中的返回值,而不实际定义它们
    SetGame(){
    中的(数字、形状、阴影、颜色)将实际定义返回值,您可以替换
    CardContent
    init
    中相应的
    $n
    ,谢谢,我将用SetGame()测试另一种方法{(数字、形状、阴影、颜色)}在我看来,这更符合通用方法以及Model和ViewModel各自的角色。不要将结束括号放在该行的末尾。在
    CardContent
    init
    之后结束。您需要做的任何事情都必须在这些括号之间,并最终
    返回汽车dContent(…)
    谢谢您的帮助,我想我终于明白了。我将在我的代码中检查它。
    func changeThings(how f: (String) -> String) -> [String] {
        let things: [String] = ["A", "B", "C", "D"]
    
        var result: [String] = []
        for thing in things {
            result.append(f(thing))
        }
        return result
    }
    
    let lc1 = changeThings(how: { string in return string.lowercased() })
    let lc2 = changeThings(how: { $0.lowercased() })
    
    func doubleString(_ s: String) -> String {
        return "\(s)\(s)"
    }
    
    let db1 = changeThings(how: doubleString(_:))
    let db2 = changeThings(how: { "\($0)\($0)" })