This is an image representation of my code below:

This is what they do:

CellWithImageX: Subclasses of UITableViewCell. They have an image and an loading indicator. Only 1 can be shown at the time.

ImageRequester: Downloads the images and gives ImageCache a callback when it's done.

FileExplorer: Saves the images.

ImageCache: Manages everything. Since I am most concerned about the current design, I think the code for the ImageCache is only relevant:

// Used to weakly hold the CellWithImageX image classes. (Is this bad?)
open class WeakObjectWrapper<T: AnyObject> {
public weak var obj: T?

public init(obj: T) {
self.obj = obj
}

}

class ImageCache {

// I can not understand how it can work if it isn't a singleton.
// From every cell, I can easily pass the reference without to much hassle.
// I am not sure for an singleton alternative.
static let sharedInstance = ImageCache()

// TODO: Maybe remove some elements from time to time?
// Yes, this is an array of the images in the table view cell...

private init() {}

// Bit concenered about a race condition.
// decide what would be the best way.

guard photoIdentifier != 0 else {

return
}

guard let image = determineImage(photoIdentifier: photoIdentifier) else {

return
}

}

func received(image: UIImage, forPhotoIdentifier: Int64) {

FileExplorer.sharedInstance.save(image: image.pngData()!, photoIdentifier: forPhotoIdentifier) // This is validated that this works, we can safely force unwrap.

// While iterating it may occur that the reference is gone.
}
}

private func determineImage(photoIdentifier: Int64) -> UIImage? {
guard let image = FileExplorer.sharedInstance.determineImage(photoIdentifier: photoIdentifier) else {

return nil
}

return image
}
}


In my cellForRowAt method in my tableView, I am calling the ImageCache handleImage method on my cell.loadableImage property.

My concerns:

• I am using a few singletons: ImageRequester, ImageCache and FileExplorer. I am not sure if this is the best approach, but I can not imagine a better way because this way, all my cells can easily register themselfs.
• I have a array of weak objects which references to the loadable images inside of a tableViewCell. Isn't there a better way?
• I am asserting I am on the main thread. If I am on multiple threads, race conditions may occur while I loop through the array. I looked into DispatchQueues and Semaphores. I just didn't found the right way to do it, and what the best way would be in my case. Does someone has a suggestion about what way would be a good way in my case?