【问题标题】:How to handle "no scene" in a scene transition attempt?如何在场景转换尝试中处理“无场景”?
【发布时间】:2016-12-07 05:22:22
【问题描述】:

在一个应该加载场景的按钮中,我正在尝试学习使用 guard 语句,但对它在四个“转义”中的每一个中的作用感到非常困惑。并且不知道我应该如何处理没有场景的情况。

此处使用哪个正确: continuereturnbreakthrow

还有……为什么?

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch: AnyObject in touches {

        let location = touch.location(in: self)

        if self.rr.contains(location) {
            guard let nextScene = goesTo
                else {print(" No such Scene ")
                continue } // continue, return, break, throw !!!!????
            loadScene(withIdentifier: nextScene)
            }
        }
    }

【问题讨论】:

  • 在你的情况下,为什么不使用 if let 而不是 guard let!在 else 下,你可以轻松地继续它。我觉得那个位置不适合用guard let!
  • 因为: 1 我想学习如何在我已经了解的流程中使用保护语句。 2.如果找不到那个场景,我希望发生一些激烈的事情,我认为这是警卫的正确位置......防范灾难......@Fay007
  • guard 语句结构通常带有return,表示如果nextScene 不存在,则返回并且什么也不做,如果存在,现在可以使用nextScene 值(这在if 中是不可能的)让)。您不能使用“继续”或“中断”,因为它们只能在循环或 switch 语句中使用。
  • @Mina 所以返回语句返回到if self.rr.contains... 范围?
  • @Confused,是的,return 只返回保护语句。指针将位于 'loadScene(withIdentifier: nextScene)' 。这个链接很有帮助->ericcerney.com/swift-guard-statement

标签: swift sprite-kit skscene


【解决方案1】:

我不认为风景适合守卫声明,因为你有很多情况下循环,你想避免一些情况!首先我们需要知道什么时候应该使用警戒语句。是的,它可以帮助您处理错误,但这并不意味着您应该随时随地使用它!

为什么要保护以及何时使用它们而不使用它们:

The Guard Statement in Swift

更新

我希望这能澄清你的问题

当你使用break时

let array: [Int?] = [3, 7, nil, 12, 40]

for arrayValue in array {

    guard let value = arrayValue else {
        print("No Value")
        break
    }

    print(value)
}

输出

3

7

没有价值

当你使用 continue 时

let array: [Int?] = [3, 7, nil, 12, 40]

for arrayValue in array {

    guard let value = arrayValue else {
        print("No Value")
        continue
    }

    print(value)

输出

3

7

没有价值

12

40

Return 将关闭函数,并且在这种情况下与 break 相同。现在请根据您的需要做出决定!如果您认为在没有场景条件的情况下可以中断它,然后中断,或者如果您想跳过它,那么只需使用 continue 跳过那个确切的场景。我希望你明白我的意思

【讨论】:

  • return 语句的效果是否与 continue 相同?
  • 返回是为了逃避正在运行的函数/方法......继续将强制增加循环的一步......所以它们不一样@Confused
【解决方案2】:

如果您处于 for 循环中,则 continue 将移动到下一次迭代,而 break 将退出 for 循环。 Return 将始终退出当前函数。

在这种情况下,您可能希望将保护语句放在 for 循环之前并退出 touchesEnded,因为我认为 goesTo 设置在其他位置。

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let nextScene = goesTo else {
        print(" No such Scene ")
        return // exit touchesEnded since goesTo is not defined 
    }

    for touch: AnyObject in touches {
        let location = touch.location(in: self)

        if self.rr.contains(location) {
            loadScene(withIdentifier: nextScene)
        }
    }
}

【讨论】:

  • 如果只考虑我的示例,在原始问题中,并且此代码在一个按钮中,并且只有一根手指在按钮上进行一次触摸......return 是真的吗? 、continuebreak 会提供相同的结果吗?
  • 感谢您的上下文和解释!也!很简洁,写的很好,很清楚。你应该考虑写文档,你有一个难得的天赋!!!由于您出色的表达所传达的洞察力和理解力,我发现了我的方法中的一个根本愚蠢之处。屏幕上有四个按钮,每个去不同的场景,每个都有这个代码,还有touchesBegantouchesMoved。但是,将一个按钮拖出并拖入另一个按钮不会激活拖入的按钮。只有第一个触摸的按钮可以重新输入,没有新的条目被确认
  • @Confused 在您的情况下,您会从 returncontinuebreak 得到基本相同的结果,但最好了解每个语句的意图并知道退出 for 循环不是与退出功能相同,例如如果您使用break 并退出for 循环,然后在for 循环之后添加代码,则此新代码将无意执行。所以最好总是应用描述你意图的命令。
  • @Confused 是否有理由允许拖动以选择按钮? UITapGestureRecognizer 会将按钮行为锁定为单击一次。
  • 我正在探索 SpriteKit、iOS 和 Swift 如何工作的许多事情,同时,从(高度)以设计师为中心的角度......这意味着试图了解什么可以和可以'不做,如何做,为什么做……等等。从设计师的角度来看,取消和改变决策(在任何时候)的能力是理想的可用性。所以我希望在这个有四个按钮的屏幕上(以迎合那些按照他们的想法行事的人)能够在中途改变他们的想法。这意味着他们可以通过拖动从一个按钮转到另一个按钮,而无需加载场景。因此使用touchesEnded 加载。
【解决方案3】:

在您的特定示例中,所有三个基本上都会做同样的事情。但是在touchesEnded 中使用循环很奇怪,因为这是最后一次触摸,而且只有一次触摸,除非您正在进行多手势操作。

如果您要在 for 循环下添加其他代码,那么您可能会破坏您的程序,因为您没有处理 guard 语句。如果您想在没有场景的情况下忽略其余功能,则使用 return 将是理想的选择。

// Break works with named labels, which can be used with while, do, and for.
// Why? Break exits loops because it's a command that redirects the
// execution of code, similar to goto in C.

outerLabel: do {
    if 0==0 { print("numbers are fun and,") }
    if 0==2 { break outerLabel } // NOTE: the label is required for
                                 // `break` when not in `while` or `switch`
    print("zero was not equal to two")
}

// Continue breaks from the current iteration (whatever value `i` is at),
// but then restarts the loop with the next value (0..1..2..3...)
for i in 1...10 {
  print(" Hello ")
  if 0==0 { continue }
  print(" Worlllddd ") // We will see 10 hellos but no worlds.
}


// Here is the example with guard
stuff: do {
  guard 0 == 2 else { break stuff } // Again, the label here is required for break.
  print(" zero is equal to two " ) // Doesn't print, lol...
}

moreStuff: for i in 1...10 {
  print(" is zero equal to two? ")
  guard 0 == 0 else { continue } // Label is optional for continue.
  print(" zero is equal to zero " ) // Does print.
}

// Here is how we use return with guard, and the print maybe explains why:
func ohLookAFunc() {
  guard 0 == 0 else {
    print(" Math and numbers as we know it are over!! ")
    return
    // ... now we xit from this crazy Func where 0 is not 0
    // You can handle this exception in any-way you see fit.
    // So if your scene doesn't exist, or if 0 is == 2, then 
    // it's up to you to figure out what to do in such disastrous
    // situations ;)
  }
  print(" Now we continue the function safe in the fact that 0 is still equal to 0")
}

这些陈述没有“最佳”用法。这仅取决于在做什么以及设置了什么逻辑。

没有人能告诉你如果找不到场景该怎么做,除了忽略输入(从touchesEnded() 返回而不做任何事情)。

或者,您可以对其进行设置,这样就可以确保始终显示正确的场景。这部分由您负责 :) 如果没有更多代码,我们无法帮助您确保这一点。

【讨论】:

  • 没有标签的 break 怎么办?它经常在while 语句中不带标签使用。我讨厌一直重复同一个问题,但这真的很简单,可以帮助我了解:在我在问题中给出的示例中,continuebreak 之间有什么不同?跨度>
  • continue 总有一些东西要发给它,它会一直持续下去。在我的问题中,breakcontinue 有何不同?
  • 在我的示例中,break 的作用与 continue 不同??????????????????????
  • 您确定来自continue 的这次崩溃吗?我有理由确定它将存在这个范围,并继续到下一个外部范围。但是我不知道,也不知道怎么查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 2014-07-29
  • 1970-01-01
  • 2012-02-28
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多