2017-11-10 77 views
0

我有一个数组(它是可选的),我尝试过滤。该数组内部有一些自定义结构的实例。他们有一个distance财产,这是一个String。现在,过滤数组的条件是这些字符串应该小于或等于某个浮点值(distance)。下面是代码:为什么我的Swift应用程序在尝试打开可选项时会抛出致命错误?

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

当我实现它,Xcode中抛出一个错误,它说,它意外地发现零而展开的可选值(一个布尔表达式的线)。然而,print方法打印distance值,所以它不是零,但是当我改变这样的打印语句:

print (Float(restaurant.distance)!) 

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

所以,我不知道Xcode会发生什么抱怨。你有什么建议吗?

+2

你如何设置'restaurant.distance'? “可选(”可能是字符串的一部分,所以它不能从它创建一个Float。 – dan

+0

@dan,是的你是对的,我通过找到两个位置之间的距离来得到它。为了保存它,我将它的类型更改为String,但String的初始化程序添加了“Optional(”前面的数字 –

回答

3

如果您restaurant.distance是一个可选的字符串,编译器会引发错误的浮标不能与类型String?,因为你不是在Float(restaurant.distance)!展开restaurant.distance形成。但它并没有让我认为这个字符串本身被存储为Optional(10999.795970332603),就像丹在你的问题的评论中指出的那样。更改该值以保存通过转换为Float的有效数字。像Paulw11指出的那样,你会失去精确性,但至少它不会崩溃。并尝试使用if let而不是强制展开,以避免发现零时崩溃。

+0

是的,你说得对,我通过找到两个位置之间的距离来得到'distance',为了保存它,我改变它的类型为String,但是String的初始化方法增加了“Optional(”在数字前面的东西,也许这就是String的新的初始化'init(描述:)),因为我距离'distance(from:)'method? –

2

基本上,你正在崩溃,因为你告诉斯威夫特崩溃如果是nil强行展开!

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

假设restaurant.distance实际上是一个可选字符串(即String?)而不是包含Optional(10999.795970332603)的字符串,您应该防御性地编码并使用条件解包。您可能还想使用Double而不是Float。 A Float只有32位,你正在失去很多的精度; 10999.795970332603作为Float是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 
}) 
相关问题