When an image is added to the store, it will be put into the cache under a unique key, and the associated Item object will be given that key. When the DetailViewController wants an image from the store, it will ask its item for the key and search the cache for the image.
Add a property to Item.swift to store the key.
Listing 15.15 Adding a new property for a unique identifier (Item.swift
)
let dateCreated: Date let itemKey: String
The image keys need to be unique for your cache to work. While there are many ways to hack together a unique string, you are going to use the Cocoa Touch mechanism for creating universally unique identifiers (UUIDs), also known as globally unique identifiers (GUIDs). Objects of type UUID represent a UUID and are generated using the time, a counter, and a hardware identifier, which is usually the MAC address of the WiFi card. When represented as a string, UUIDs look something like this:
4A73B5D2-A6F4-4B40-9F82-EA1E34C1DC04
In Item.swift, generate a UUID and set it as the itemKey.
Listing 15.16 Generating a UUID (Item.swift
)
init(name: String, serialNumber: String?, valueInDollars: Int) { self.name = name self.valueInDollars = valueInDollars self.serialNumber = serialNumber self.dateCreated = Date() self.itemKey = UUID().uuidString }
Then, in DetailViewController.swift, update imagePickerController(_:didFinishPickingMediaWithInfo:) to store the image in the ImageStore.
Listing 15.17 Storing the image (DetailViewController.swift
)
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { // Get picked image from info dictionary let image = info[UIImagePickerControllerOriginalImage] as! UIImage // Store the image in the ImageStore for the item's key imageStore.setImage(image, forKey: item.itemKey) // Put that image on the screen in the image view imageView.image = image // Take image picker off the screen - you must call this dismiss method dismiss(animated: true, completion: nil) }
Each time an image is captured, it will be added to the store. Notice that the images are saved immediately after being taken, while the instances of Item are saved only when the application enters the background. You save the images right away because they are too big to keep in memory for long.
Both the ImageStore and the Item will know the key for the image, so both will be able to access it as needed (Figure 15.9).
Similarly, when an item is deleted, you need to delete its image from the image store. In ItemsViewController.swift, update tableView(_:commit:forRowAt:) to remove the item’s image from the image store.
Listing 15.18 Deleting the image from the ImageStore
(ItemsViewController.swift
)
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { // If the table view is asking to commit a delete command... if editingStyle == .delete { let item = itemStore.allItems[indexPath.row] // Remove the item from the store itemStore.removeItem(item) // Remove the item's image from the image store imageStore.deleteImage(forKey: item.itemKey) // Also remove that row from the table view with an animation tableView.deleteRows(at: [indexPath], with: .automatic) } }