Downloading the Image Data: FATAL ERROR

I’m trying to load the photos into the interface. I checked all of the code and connections
countless times, but it still gave me the same error. I added the code on pages 432-434 which only adds to PhotosViewController.swift and Photo.swift, but the error is coming from PhotoCollectionViewCell.swift. It looks like the code found the photos and started logging the photos into the console but then crashed and never loaded the photos.

Does anybody have ideas? What am I missing? TIA

Here is the error I’ve been getting:

Successfully found 100 photos

2020-08-12 14:58:18.271777-0700 Photorama[64192:4012203] [Storyboard] Unknown class ImageView in Interface Builder file.

2020-08-12 14:58:18.273968-0700 Photorama[64192:4012203] [Storyboard] Unknown class ImageView in Interface Builder file.

2020-08-12 14:58:18.275442-0700 Photorama[64192:4012203] [Storyboard] Unknown class ImageView in Interface Builder file.

2020-08-12 14:58:18.334039-0700 Photorama[64192:4012203] [Storyboard] Unknown class ImageView in Interface Builder file.

2020-08-12 14:58:18.335395-0700 Photorama[64192:4012203] [Storyboard] Unknown class ImageView in Interface Builder file.

Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/sarahchang/Desktop/Summer Projects/Photorama/Photorama/PhotoCollectionViewCell.swift, line 20

2020-08-12 14:58:18.584343-0700 Photorama[64192:4012203] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/sarahchang/Desktop/Summer Projects/Photorama/Photorama/PhotoCollectionViewCell.swift, line 20

(lldb)

Photo.swift

import Foundation

class Photo: Codable {
let title: String
let remoteURL: URL?
let photoID: String
let dateTaken: Date?

enum CodingKeys: String, CodingKey {
    case title
    case remoteURL = "url_z"
    case photoID = "id"
    case dateTaken = "date_taken"
}
}

extension Photo: Equatable {
static func == (lhs: Photo, rhs: Photo) -> Bool {
    // Two Photos are the same if they have the same photoID
    return lhs.photoID == rhs.photoID
}
}

PhotosViewController.swift

import UIKit

class PhotosViewController: UIViewController, UICollectionViewDelegate {

@IBOutlet var collectionView: UICollectionView!
var store: PhotoStore!
let photoDataSource = PhotoDataSource()

override func viewDidLoad() {
    super.viewDidLoad()
    
    
    
    collectionView.dataSource = photoDataSource
    collectionView.delegate = self
    
    store.fetchInterestingPhotos {
        (photosResult) in
        
        switch photosResult {
        case let .success(photos):
            print("Successfully found \(photos.count) photos")
            self.photoDataSource.photos = photos
        case let .failure(error):
            print("Error fetching interesting photos: \(error)")
            self.photoDataSource.photos.removeAll()
        }
        self.collectionView.reloadSections(IndexSet(integer: 0))
    }
    
    
    }

func collectionView(_ collectionView: UICollectionView,
                    willDisplay cell: UICollectionViewCell,
                    forItemAt indexPath: IndexPath) {
    
    let photo = photoDataSource.photos[indexPath.row]
    
    // Download the image data, which could take some time
    store.fetchImage(for: photo) { (result) -> Void in
        
        // The index path for the photo might have changed between the
        // time the request started and finished, so find the most
        // recent index path
        guard let photoIndex = self.photoDataSource.photos.firstIndex(of: photo),
            case let .success(image) = result else {
                return
        }
        let photoIndexPath = IndexPath(item: photoIndex, section: 0)
        
        // When the request finishes, find the current cell for this photo
        if let cell = self.collectionView.cellForItem(at: photoIndexPath)
            as? PhotoCollectionViewCell {
            cell.update(displaying: image)
        }
    }
}

}

PhotoCollectionViewCell

 import UIKit

class PhotoCollectionViewCell: UICollectionViewCell {

@IBOutlet var imageView: UIImageView!
@IBOutlet var spinner: UIActivityIndicatorView!


func update(displaying image: UIImage?) {
    if let imageToDisplay = image {
        spinner.stopAnimating()
        imageView.image = imageToDisplay
    } else {
        spinner.startAnimating()
        imageView = nil
    }
}
}

Did you check to make sure that all outlets are properly connected to required objects in interface builder?

I’m pretty sure all of my outlets are connected properly, but just to check, here are what my outlets are connected to:
Screen Shot 2020-08-14 at 8.57.48 AM Screen Shot 2020-08-14 at 8.58.01 AM

The outlet connections look good.

But what’s on line 20 in PhotoCollectionViewCell.swift? That line is not visible in the code posted above.

By the way, next time, to make it more readable, please post your code between a pair of three back-tick marks like this:
```
Paste code here…
```

For example:

import UIKit

class PhotoCollectionViewCell: UICollectionViewCell {

@IBOutlet var imageView: UIImageView!
@IBOutlet var spinner: UIActivityIndicatorView!


func update(displaying image: UIImage?) {
    if let imageToDisplay = image {
        spinner.stopAnimating()
        imageView.image = imageToDisplay
    } else {
        spinner.startAnimating()
        imageView = nil
    }
}
}

Also:

Did you investigate those Unknown class messages?

1 Like

I’ll second ibex10’s recommendation to figure out those Unknown class errors in the storyboard. If something’s wrong in your storyboard, that could cause problems with your outlet connections which in turn could cause the optional unwrapping errors.

Thanks for your tip ibex10! Line 20 in PhotoCollectionView Cell.swift is

imageView.image = imageToDisplay

I investigated the Unknown class in the error and found that I had accidentally named imageView a separate class and it was a mistake. I changed it to no custom class and ran the app. It now gives me this error:

Successfully found 100 photos

Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/Danvers25/Desktop/Summer Projects/Photorama 2/Photorama/PhotoCollectionViewCell.swift, line 20

2020-08-15 15:13:41.754882-0700 Photorama 2[75855:4733663] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/Danvers25/Desktop/Summer Projects/Photorama 2/Photorama/PhotoCollectionViewCell.swift, line 20

(lldb)

In that case, given that

@IBOutlet var imageView: UIImageView!
@IBOutlet var spinner: UIActivityIndicatorView!

func update(displaying image: UIImage?) {
    if let imageToDisplay = image {
        spinner.stopAnimating()
        imageView.image = imageToDisplay
    } else {
        spinner.startAnimating()
        imageView = nil
    }
}

imageView outlet itself is a strong suspect!

Can you see why? I let you discover it yourself as a learning exercise :slight_smile:

I figured it out!! :woman_facepalming: Thanks for all of your help! For those in the future who might have the same problem, here’s what was wrong:
I wrote:

imageView = nil

Instead of:

imageView.image = nil