I have a group of local UIImage
s that I need to load and present in successive order when their respective cell is tapped. For example, I have 20 images of a hot dog that combine to form an animation. When the user taps the hot dog cell, the cell's UIImageView
should animate the images.
I know how to use UIImageView
's animationImages
to achieve the animation. My problem is that retrieving all of these images from disk takes ~1.5 seconds and blocks the main thread.
I could instantiate a helper class in application(_:didFinishLaunchingWithOptions:)
that loads these images from disk on a background thread so that they'll be in memory when needed, but this seems hacky.
Are there any better ways of quickly loading many images from disk?
Edit: These images are illustrations and thus are .png.
Edit2: Assume the sum of each image sequence is 1 MB. The image dimensions I'm testing with are 33-60% larger than the UIImageView
's @3x requirements. I am waiting to confirm final UIImageView
size before getting correct image sets from our designers, so the time should be cut significantly with properly sized assets, but I'm also testing on a physical iPhone X.
class ViewModel {
func getImages() -> [UIImage] {
var images: [UIImage] = []
for i in 0..<44 {
if let image = UIImage(named: "hotDog\(i).png") {
images.append(image)
}
}
return images
}
}
class ViewController: UIViewController {
private var viewModel: ViewModel!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! CustomCell
let images = viewModel.getImages()
cell.animateImageView(withImages: images)
}
}
class CustomCell: UITableViewCell {
@IBOutlet weak var imageView: UIImageView!
func animateImageView(withImages images: [UIImage]) {
imageView.image = images.last
imageView.animationImages = images
imageView.animationDuration = TimeInterval(images.count / 20)
imageView.animationRepeatCount = 1
imageView.startAnimating()
}
}
I would suggest you try
UIImage(contentsOfFile:)
instead ofUIImage(named:)
. In my quick test and found it to be more than an order of magnitude faster. It's somewhat understandable because it's doing a lot more (searching for the asset, cacheing the asset, etc.).Note, this presumes that you had the files in the resource directory, and you may have to modify this accordingly depending upon where they are in your project. Also note that I avoided doing
Bundle.main.url(forResource:withExtension:)
within the loop, because even that had an observable impact on performance.