ajayb
ajayb

Reputation: 633

UIImage showing nil

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

Answers (2)

dfrib
dfrib

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

Tom Harrington
Tom Harrington

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, or
  • photo has a valid name but the file is somehow corrupt to the point where UIImage can't handle it, or
  • decompressedImage is returning nil, because UIGraphicsGetImageFromCurrentImageContext for some reason.

Upvotes: 1

Related Questions