Reputation: 633
I'm having issues with my project. I'm new to coding. I keep getting the error fatal error: unexpectedly found nil while unwrapping an Optional value (lldb). It seems that the variable "image" is not producing an image and instead producing "nil". the variable "photo" is producing a name that corresponds with my JPG image name. For some the variable "image" is not able to produce that UIImage and rather is producing nil. Hopefully you can help me.
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)
}
}
I have a feeling that it has to do with the decompression of the image:
import UIKit
extension UIImage {
var decompressedImage: UIImage {
UIGraphicsBeginImageContextWithOptions(size, true, 0)
drawAtPoint(CGPointZero)
let decompressedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return decompressedImage
}
}
Upvotes: 1
Views: 1493
Reputation: 73166
There are many things going on here that might go wrong at runtime. So I'll focus on one, and advice you to be careful with force unwrapping (optionalProperty!
) unless you know your optionals and in which situations it's ok to use force unwrapping. If you don't yet know the latter, you should avoid !
.
Let's look at this segment of code
let image = UIImage(named: photo!)?.decompressedImage
As you mention, photo
is an optional string that might be nil. But if we look at the class reference or UIImage, specifically the initialiser UIImage(named: ...)
, it specifies
init?(named name: String)
I.e., the parameter named
should be a string. nil
is not a string and hence your error.
If we proceed to assume that photo
actually forcefully unwrapped to a string (path), we have our next problem; "Value of type UIImage has no member 'decompressedImage'". Looking back at the class reference for UIImage
, we can't find this method here.
Anyway, I suggest read up on optionals and optional chaining in swift (if let
, guard let
, error handling), e.g.
In your specific case, you need to handle, at the very least, the case where expression dictionary["Photo"] as? String
returns nil
.
Upvotes: 0
Reputation: 70936
Most likely it's these two lines:
let image = UIImage(named: photo!)?.decompressedImage
self.init(caption: caption!, comment: comment!, image: image!)
The first line assigns a value to image
but specifically allows for a nil value. That's what the ?
implies. Also, in decompressedImage
(the purpose of which is... unclear) the call to UIGraphicsGetImageFromCurrentImageContext
is allowed to return nil.
Then in the second line you use image!
without checking whether it's nil. It is nil, according to your crash, which implies that one of the following is true:
photo
doesn't actually contain the name of an image in your app bundle, orphoto
has a valid name but the file is somehow corrupt to the point where UIImage
can't handle it, ordecompressedImage
is returning nil, because UIGraphicsGetImageFromCurrentImageContext
for some reason.Upvotes: 1