我目前有一个UITableView,它包含一系列事件。每个事件都有一个按钮,用户可以按下该按钮以访问与事件相关的照片的更大视图。我已连接并设置了UIButton,但我很难在新窗口中设置图像。这是我的功能:
func largeMap(sender: UIButton!) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let manager = NSFileManager.defaultManager()
self.performSegueWithIdentifier("largeMapView", sender: self)
println(sender.tag.description)
println(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")
if let image = UIImage(data: manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")!) {
largeMapView.image = image
}
}
当我运行应用程序时,它崩溃在largeMapView.image = image并且给了我"致命错误:在解开一个Optional值"时意外地发现了nil。我已经检查过,图像的路径是正确的,它正在访问图像,但是它无法将其设置为UIImageView。我将UIImageView插座设置在类的顶部。为什么会这样?我之前已经以这种方式设置了UIImageView,但它现在还没有成功。
答案 0 :(得分:2)
基本上问题是你使用感叹号。感叹号永远不会安全!它们可能是一种“难闻的气味”,一种危险的信号 - 在你的代码中,就是它们的本质。
(1)
我将UIImageView插座设置在班级的顶部。
但是你没有显示如何设置。您没有显示largeMapView
是什么或如何声明。声明可能如下所示:
@IBOutlet var largeMapView : UIImageView!
如果是这样,那很糟糕 - 这是一个隐式解包的可选项,这意味着它可能是零。这可能是您问题的根源。通过使用有条件解包的可选项,您可以解决问题 - 直到您尝试设置为nil,然后崩溃。如果从未正确设置,那就是崩溃的原因。
(2)
沿着相同的路线,代码的其余部分也不应强制解包Optionals(使用!
后缀运算符),除非您知道某些它们永远不会是零。像这样重写,以便有条件且安全地解包每个Optional:
if let d = manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png") {
if let image = UIImage(data: d) {
largeMapView.image = image
}
}
这样,如果contentsAtPath
失败或UIImage(data:)
失败,则不会发生任何事情 - 您不会设置图片 - 但至少您不会崩溃。您可以在调试器中使用步进来确定 失败的位置。 - 但是如果问题是largeMapView
是一个隐式解包的nil,那么即使这样也无法拯救你。