Swift:在touchesBegan中使用switch语句

4

我希望清理我的touchesBegan(..)SKScene中的代码。我想用一个case语句代替我的if .. else链。但是,在实现时出现了错误,这表明我不知道等式是如何在幕后进行的。

代码之前:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)

        if self.nodeAtPoint(location) === playLabel {
            buildLevelSelect()
        } else if self.nodeAtPoint(location) === aboutLabel {
            createAboutView()
        } else if self.nodeAtPoint(location) === storeLabel {
            createStore()
        }
    }
}

代码后:点击一些标签可以正常工作,但是其他一些标签会出现Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode 0x0)错误:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)

        switch(self.nodeAtPoint(location)){
        case playLabel :
            buildLevelSelect()
        case aboutLabel :
            createAboutView()
        case storeLabel :
            createStore()
        default : break
    }
}
3个回答

5

如果您想要 === 的行为,可以编写一种看起来有点奇怪但功能正常的 switch,如下所示:

switch(true){
        case self.nodeAtPoint(location) === playLabel : buildLevelSelect()
        case self.nodeAtPoint(location) === aboutLabel : createAboutView()
        case self.nodeAtPoint(location) === storeLabel : createStore()
        default : break
}

在我看来,这种写法比if-else语句更加简洁易懂。

1
哦...跳出思维定势,我喜欢这个。在接受答案之前,我会等一两天来感受其他人的想法。 - cdpalmer

4

最简单的实现方式是通过填充节点的 .name 属性,这样你就可以根据名称进行切换。因此,您的 switch 语句将如下所示:

switch (self.nodeAtPoint(location).name ?? "") { 
    case "playLabel" :
        buildLevelSelect()
    case "aboutLabel" :
        ...

1
这是最好的方法。@cdpalmer,你应该检查一个字符串是否等于另一个字符串(名称),而不是比较两个可能不同的对象,即使你使用二进制运算符===(例如,如果一个是String而另一个是NSString,则两个相同的字符串会导致崩溃)... - Alessandro Ornano
这很有道理。我得进行一些重构,因为我在我的副业项目中才发现你可以将字符串名称与对象绑定。 - cdpalmer

3

你也可以在switch语句中转换对象,这样你的代码就能按预期工作。

    if let touch = touches.first as UITouch! {

        let touchLocation = touch.location(in: self)

        switch self.atPoint(touchLocation) {
            case redBox as SKSpriteNode:
                print("touched redBox")
            case greenBox as SKSpriteNode:
                print("touched greenBox")
            default:
                print("touched nothing")
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接