swift,unwrapped required中的选项

时间:2015-04-28 04:28:45

标签: swift

我不确定为什么/如何运作。我有一个用于创建NSManagedObject子类的方法:

public func createWithPlacemark(placemark: CLPlacemark) -> AddressAnnotation {
        let entity = NSEntityDescription.insertNewObjectForEntityForName("AddressAnnotation", inManagedObjectContext: managedObjectContext) as! AddressAnnotation

        return updateAnnotation(entity, withPlacemark: placemark)
    }

    public func updateAnnotation(annotation: AddressAnnotation, withPlacemark placemark: CLPlacemark) -> AddressAnnotation {
        annotation.address = placemark.subThoroughfare
        annotation.street = placemark.thoroughfare
        annotation.city = placemark.locality
        annotation.state = placemark.administrativeArea
        annotation.zip = placemark.postalCode

        if !placemark.name.isEmpty {
            annotation.name = placemark.name
        }
        else if placemark.areasOfInterest[0] as? String != nil{
            annotation.name = placemark.areasOfInterest[0] as! String
        }
        else {
            annotation.name = ""
        }

        annotation.latitude = placemark.location.coordinate.latitude
        annotation.longitude = placemark.location.coordinate.longitude

        return annotation
    }

据我所知,这两种方法都没有返回可选项。 insertNewObjectForEntityForName返回AnyObject,而不是AnyObject?。

当我调用此代码时,它看起来像这样:

let geocoder = CLGeocoder()
            geocoder.geocodeAddressString(string, completionHandler: {
                (placemarks, error) -> Void in

                // Check for returned placemarks
                if let placemarks = placemarks where placemarks.count > 0 {
                    let topResult = placemarks[0] as! CLPlacemark

                    let address = self.addressAnnotationLogic?.createWithPlacemark(topResult)


                    if address!.name.isEmpty {
                        address!.name = string
                    }


                }
            })

当我调用createWithPlacemark时,address不是可选的。如果我尝试在行的末尾添加!,则会出现编译错误。这对我来说很有意义。

但是,当我尝试在if语句中使用该地址时

if address!.name.isEmpty {

我需要使用力量展开。这是为什么?地址变量首先不是可选的,因为createWithPlacemark返回一个值,而不是一个可选的。

1 个答案:

答案 0 :(得分:0)

bang!是必需的,因为您在此行中使用了optional chaining

let address = self.addressAnnotationLogic?.createWithPlacemark(topResult)

当您使用可选链接时,如果链中的任何链接为nil,则整个表达式返回nil,并且结果是否为nil,表达式始终求值为一个Optional值。

addressAnnotationLogic?表示addressAnnotationLogic是某种Optional,这意味着它可能是nil。如果addressAnnotationLogic?nil,那么整个表达式self.addressAnnotationLogic?.createWithPlacemark(topResult)将评估为nil。如果不是nil,则address仍为Optional值。

一个建议是使用新的if let语法来解包代码中的所有潜在Optional值,如下所示:

if let placemarks = placemarks where placemarks.count > 0,
   let topResult = placemarks[0] as? CLPlacemark,
   let address = self.addressAnnotationLogic?.createWithPlacemark(topResult) {
       if address.name.isEmpty {
           address.name = string
       }
}

这将产生运行时错误的可能性大大降低。使用!是有风险的。