我不确定为什么/如何运作。我有一个用于创建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返回一个值,而不是一个可选的。
答案 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
}
}
这将产生运行时错误的可能性大大降低。使用!
是有风险的。