viewDidLoad 中的调用函数崩溃

calling function in viewDidLoad crash

调用 parseString 使我的应用程序崩溃。 myOptionalString 是从表视图中的 didSelectRowAtIndexPath 设置的。信息肯定会传递给这个视图控制器。

如果通过按下按钮调用,该方法也有效。但是在任何生命周期方法中,我尝试在展开一个 Optional 时意外地发现 nil。

override func viewDidLoad() {
    super.viewDidLoad()   
    if let myUnwrappedString = myOptionalString{
         print(myUnwrappedString) //<-- prints out string
         confidence.text = parseString(myUnwrappedString) //<-- unexpectedly found nil while unwrapping an Optional crash
    }        
}

//this method works if called on a button press but crashes in viewDidLoad
func parseString(myString: String)->String{
    return myString.substringFromIndex(myString.rangeOfString(" ")!.endIndex)
}

我猜你的问题出在这一行:

myString.rangeOfString(" ")!

rangeOfString return 是一个可选的 Range<Index>? 值,这意味着如果您要查找的字符不在字符串中,您将获得值 nil 在 return。换句话说,如果您的字符串中没有 space,您的范围会得到一个 nil 值。

然后用 ! 强制展开该值,然后用它调用 substringFromIndex。这意味着,如果范围实际上是 nil,您可以使用该 nil 值尝试从其 endIndex 创建一个子字符串...您不能...所以它崩溃了。

解决这个问题的一种方法是使用 guard 来确保您确实在字符串中找到了一个范围。如果你不这样做,那么你只是 return 一个空的 String...或者做一些更适合你的用例的事情。

这是一个例子:

func parseString(myString: String)->String{
    guard let range = myString.rangeOfString(" ") else {
        return ""
    }
    return myString.substringFromIndex(range.endIndex)
}

希望对你有所帮助。

您的错误来自您的函数 parseString,让我们看看原因。如果您仔细观察您的函数,您将 force-unwrapping 设为可选值 myString.rangeOfString(" ")!。完全不推荐这样做。

如果我们将字符串 "Confidence: 63%" 传递给函数,该函数将正常工作,并且 returns "63%",但它会工作,因为它内部有 " " 字符串,如果由于某种原因你传递了一些没有它的字符串,它会崩溃(例如 "Confidence:63%")。

因此,实现此功能的正确方法之一是使用 guard 语句,使用可选绑定避免任何 force-unwrapping:

func parseString(myString: String) -> String? {
   guard let range = myString.rangeOfString(" ") else { return nil }
   return myString.substringFromIndex(range.endIndex)
}

在上面的函数中,你 return nil 以防字符串中不存在 " " 并避免运行时错误。

希望对你有所帮助。