我的项目有问题。我是编码新手。我一直得到错误致命错误:在展开可选值时意外发现nil(lldb)。变量"image"似乎并没有产生图像,而是产生"nil"。变量"photo"产生了一个与我的JPG图像名称相对应的名称。对一些人来说,变量"image"不能产生UIImage,而是产生nil。希望你能帮助我。
import UIKit
class Photo {
class func allPhotos() -> [Photo] {
var photos = [Photo]()
if let URL = NSBundle.mainBundle().URLForResource("Photos", withExtension: "plist") {
if let photosFromPlist = NSArray(contentsOfURL: URL) {
for dictionary in photosFromPlist {
let photo = Photo(dictionary: dictionary as! NSDictionary)
photos.append(photo)
}
}
}
return photos
}
var caption: String
var comment: String
var image: UIImage
init(caption: String, comment: String, image: UIImage) {
self.caption = caption
self.comment = comment
self.image = image
}
convenience init(dictionary: NSDictionary) {
let caption = dictionary["Caption"] as? String
let comment = dictionary["Comment"] as? String
let photo = dictionary["Photo"] as? String
let image = UIImage(named: photo!)?.decompressedImage
self.init(caption: caption!, comment: comment!, image: image!)
}
func heightForComment(font: UIFont, width: CGFloat) -> CGFloat {
let rect = NSString(string: comment).boundingRectWithSize(CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(rect.height)
}
}
我有一种感觉,这与图像的解压缩有关:
导入UIKit
扩展UIImage{
var decompressedImage: UIImage {
UIGraphicsBeginImageContextWithOptions(size, true, 0)
drawAtPoint(CGPointZero)
let decompressedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return decompressedImage
}
}
很可能是这两行:
let image = UIImage(named: photo!)?.decompressedImage
self.init(caption: caption!, comment: comment!, image: image!)
第一行为image
指定一个值,但特别允许零值。这就是?
的含义。此外,在decompressedImage
(其目的…不清楚)中,允许对UIGraphicsGetImageFromCurrentImageContext
的调用返回nil。
然后在第二行中使用image!
,而不检查它是否为零。根据您的崩溃情况,它为零,这意味着以下情况之一为真:
photo
实际上并不包含应用程序捆绑包中图像的名称,或者photo
有一个有效的名称,但文件以某种方式损坏到UIImage
无法处理的程度,或者decompressedImage
返回nil,因为UIGraphicsGetImageFromCurrentImageContext
出于某种原因
这里有很多事情可能在运行时出错。因此,我将重点讨论一个,并建议您小心强制展开(optionalProperty!
),除非您知道您的选项以及在哪些情况下可以使用强制展开。如果你还不知道后者,你应该避免!
。
让我们看看这段代码
let image = UIImage(named: photo!)?.decompressedImage
正如您提到的,photo
是一个可选字符串,可能为nil。但是,如果我们查看类引用或UIImage,特别是初始化程序UIImage(named: ...)
,它指定
init?(named name: String)
也就是说,参数named
应该是一个字符串。nil
不是字符串,因此会出现错误。
如果我们继续假设photo
实际上被强制展开为字符串(路径),我们就有了下一个问题"UIImage类型的值没有成员'depressedImage'"。回顾UIImage
的类引用,我们在这里找不到这个方法。
无论如何,我建议阅读swift中的选项和可选链接(if let
,guard let
,错误处理),例如
- 可选链接
在您的特定情况下,至少需要处理表达式dictionary["Photo"] as? String
返回nil
的情况。