3. For a tougher challenge, take the image generation code out of cellForRowAt: generate all images when the app first launches, and use those smaller versions instead. For bonus points, combine the getDocumentsDirectory() method I introduced in project 10 so that you save the resulting cache to make sure it never happens again.
As a reminder, here’s the code for getDocumentsDirectory():
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
The above is from
Day 98 of Paul Hudson's excellent course:
100 Days of Swift. It is Challenge #3 and there is even a "bonus" challenge inside the challenge! In approaching the solution--before coding--I wrote down my thoughts and then gathered snippets of code that I thought would help. My notes are below. I thought it might be helpful for others to share them without giving away the solution.
First, I jotted down the four main things I was concerned with:
- Read big images from bundle, see project 1.
- Render a image into a rect using CoreGraphics like in project 30.
- Read the thumbnails in like project 10.
- If a thumbnail does not exist then create it. Also like in project 10.
Next, I gathered the corresponding snippets of the code:
From project 1:
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)
let pictureNames = items
.filter { $0.hasPrefix("nssl") }
.sorted { $0 < $1 }
self?.storms = pictureNames.map {
Storm(name: $0, imageName: $0) }
DispatchQueue.main.async { [weak self] in
self?.collectionView.reloadData()
}
}
From project 30:
let path = Bundle.main.path(forResource: imageRootName, ofType: nil)!
let original = UIImage(contentsOfFile: path)!
let renderRect = CGRect(origin: .zero, size: CGSize(width: 90, height: 90))
let renderer = UIGraphicsImageRenderer(size: renderRect.size)
let rounded = renderer.image { ctx in
ctx.cgContext.addEllipse(in: renderRect)
ctx.cgContext.clip()
original.draw(in: renderRect)
}
From project 10:
Write:
let imageName = UUID().uuidString
let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)
if let jpegData = image.jpegData(compressionQuality: 0.8) {
try? jpegData.write(to: imagePath)
}
Read:
let path = getDocumentsDirectory().appendingPathComponent(person.imageName)
cell.imageView.image = UIImage(contentsOfFile: path.path)