当我尝试打开可选项时,为什么我的Swift应用程序会抛出致命错误?

时间:2017-11-10 20:35:04

标签: arrays swift filtering

我有一个数组(它是可选的)我尝试过滤。在该数组内部有一些自定义结构的实例。它们的distance属性为String。现在,过滤数组的条件是这些字符串应小于或等于某个浮点值(distance)。这是代码:

filteredUnitRestaurants = anotherUnitRestaurant?.filter({ (restaurant) -> Bool in
    print (restaurant.distance)
    return Float(restaurant.distance)! <= Float(distance)
})

当我实现它时,Xcode会抛出一个错误,它表示在展开Optional值时(在布尔表达式的行中)意外地发现了nil。但是,print方法打印distance值,因此它不是nil,但是当我像这样更改print语句时:

print (Float(restaurant.distance)!)

它也会引发错误。所以,我认为问题与将字符串值转换为float有关,但distance的值只是一个数字。当我在控制台上打印它时,它看起来像这样:Optional(10999.795970332603)

所以,我不知道是什么让Xcode抱怨。你有什么建议吗?

2 个答案:

答案 0 :(得分:3)

如果您的restaurant.distance是一个可选字符串,编译器会抛出一个错误,即无法使用String?类型形成Float,因为您不能将restaurant.distance解包Float(restaurant.distance)!。但它没有让我认为字符串本身被存储为Optional(10999.795970332603),就像你在问题的评论中指出的那样。将其更改为保存将转换传递给Float的有效数字。你会像Paulw11指出的那样失去精确度,但至少它不会崩溃。并尝试使用if let而不是强制解包,以避免在找到nil时崩溃。

答案 1 :(得分:2)

基本上你是因为告诉Swift崩溃,如果nil通过!强行解包而导致崩溃

为什么你得到nil我不能说,因为该值可以成功转换为Float;也许它正在崩溃其他一些数据,或者字符串可能是Optional(10999.795970332603) - 在这种情况下,你在其他地方有一个问题,你正在创建该字符串值而没有正确地解包值。

假设restaurant.distance实际上是一个可选字符串(即。String?)而不是包含Optional(10999.795970332603)的字符串,您应该采取防御性编码并使用条件解包。

您可能还想使用Double代替FloatFloat只有32位,你会失去很多精度;作为Float的10999.795970332603是10999.8而作为Double它是10999.7959703326。

最后,在过滤之前将distance转换为Double;你每次都在进行不必要的工作

let doubleDistance = Double(distance)
filteredUnitRestaurants = anotherUnitRestaurant?.filter({ (restaurant) -> Bool in
    guard let distanceStr = restaurant.distance, 
          let restaurantDistance = Double(distanceStr) else {
              return false
    }
    return restaurantDistance <= doubleDistance
 })