【问题标题】:How to correctly and efficiently unwrap these optionals?如何正确有效地解开这些选项?
【发布时间】:2017-08-16 09:30:46
【问题描述】:

是的,这是另一个可选问题... :(

每次我认为我开始很好地掌握可选选项时,Xcode 都会向我抛出一个错误修复建议,用于展开。以下代码块使用了所有 Xcodes 错误修复。但我不认为这是这样做的正确方法。

var btAdd = [SKSpriteNode]()
var btLose = [SKSpriteNode]()

...

let touchedNodes = self.nodes(at: pos)

for node in touchedNodes{
    if btAdd.contains((node as? SKSpriteNode)!) {
        let index = Int(String(describing: node.name?[(node.name?.endIndex)!]))
        node.isHidden = true
        btLose[index!].isHidden = false
        var dogTeam = defaults.array(forKey: "dogTeam") as! [Int]
        dogTeam.append(index!)
        defaults.set(dogTeam,forKey: "dogTeam")
    }
}

我开始做...

if let node as? SKSpriteNode{
   if btAdd.contains(node){
      ...
   }
}

但我也不确定。

我正在寻找有关执行此代码块的绝对“正确”方法的一些指导。不仅是 .contains 部分,还有 index 和 UserDefaults 数组的展开。

【问题讨论】:

  • btAdd 是什么类型的?
  • [SKSpriteNode],坏名声,我知道。我将添加声明。
  • 这很简单,如果您 100% 确定 optional 具有其基础值,那么您可以使用强制解包(由您自己负责),否则您应该安全地解包 optional(例如使用 if let 语法)。没有“正确的方法”,您有责任确定如何使用可选项。

标签: xcode swift3 sprite-kit optional


【解决方案1】:

实际上,您的代码的最后一部分似乎没问题。这只是需要稍微调整的第一部分。你“开始做”的事情也很好,但这是另一个版本:

for node in touchedNodes where node as? SKSpriteNode != nil &&
    btAdd.contains(node as! SKSpriteNode){

如果你使用上面的,你甚至不需要循环中的if语句。

您似乎对在哪里强制展开以及在哪里不展开感到很困惑。请记住,只有当您绝对确定要解包的内容不能为 nil 时,您才强制解包。

这条线看起来很糟糕:

let index = Int(String(describing: node.name?[(node.name?.endIndex)!]))

您似乎想获取节点名称的最后一个字符并将其转换为 int。由于您首先检查了节点是否在数组中,因此我认为在这里强制展开是安全的。 (我假设数组中的所有节点都有一个以数字结尾的名称)另外,要获取最后一个字符,只需执行 str.character.last:

let index = Int(node.name!.characters.last!.description)!

【讨论】:

  • 是的,我同意这条线看起来很难看,我首先尝试了.last 与你那里的确切线,但这会引发错误inout String is not convertible to String。所以我尝试了使用characters.last! 的其他变体,但我不断收到不同的警告和错误。一个是像 CharacterView_Element cannot be convert to Int? 之类的东西,或者类似的东西。
  • @TheValyreanGroup 我的错!我错过了那里的description。查看编辑后的答案!
  • 漂亮,这很有效,而且比其他方式更干净。我不知道需要description。谢谢你。
  • @TheValyreanGroup 如果您认为我的回答回答了您的问题,请考虑接受!
  • 你编辑的for循环看起来很棒,很有意义,我会使用它,但是我需要循环中的if btAdd.contains,因为我有一个else,只是没有发布它。
【解决方案2】:

您还可以将选项包装在 if 语句中,以消除它们的“可选性”。每当我引用它时,第一个示例索引就变得非可选

    if let index = Int(spinButton.name!) {
        let something = someArray[index]
    }

你的方式... index2 每次被引用时总是可选的

    let index2 = Int(spinButton.name!)
    let something = someArray[index2!] 

【讨论】:

  • 如果我知道spinButton.name 永远不会为零,这真的很重要吗?除了必须使用的事实!
  • 你误读了这个。我们没有确认 spinButton.name 不是 nil。我们确保索引总是有一个 Int 值,我们以后不必担心它在代码中或将其视为可选
  • 你不是两种都做吗? 如果 spinButton.name 为 nil 则将 index 初始化为 Int?
  • 没关系,我现在看到了。您确保它是 Int 值而不是 String 或其他值,对吗?
  • 正确。如果每次引用“索引”时都查看原始代码块,则必须将其视为可选的“索引!” ,我只是说你将这些可选参数包装在一个 if 语句中,你以后不必将它们视为可选参数
猜你喜欢
  • 1970-01-01
  • 2015-06-30
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多