Supporting SwiftUI with Core Graphics

Nov 22 2022 · Swift 5.5, iOS 15, Xcode 13

Part 1: Supporting SwiftUI with Core Graphics

07. Create a Thumbnail

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 06. Shading with Pencil Next episode: 08. Color Picking from a Bitmap Image

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 07. Create a Thumbnail

We’ve got one important piece missing from our drawing pad implementation. We aren’t storing our drawings, and we can’t see a thumbnail version in the mindmap cell. We’ll fix that up in this episode, with some more help from UIGraphicsImageRenderer.

Model.swift

We’ll start with updating the cell’s model, in CellModel.swift

Just like we did in DrawingPadView, we’ll replace the original drawing with a UIImage.

var drawing: 🟩UIImage?

Adjust the update drawing method the same way.

mutating func update(drawing: 🟩UIImage) {
  self.drawing = drawing
}

And the method down in CellStore.

  func updateDrawing(cell: Cell, drawing: 🟩UIImage) {

CellView.swift

We’ll need to update the actual cell view, as well. Down in the body, find the if statement checking for a drawing. And replace this drawing view, with an Image made from our drawing UIImage.

Image(uiImage: drawing)

DrawingPadView.swift

Back in DrawingPadView.swift, we can uncomment the code in the save button, and because we updated the underlying types and CellStore method, this will just work!

if let cell = cellStore.selectedCell,
 let drawing = drawing {
  cellStore.updateDrawing(cell: cell, drawing: drawing)
}

ContentView.swift

One more thing, in ContentView.swift, we need to pass the selected cell’s drawing into the drawing pad again.

DrawingPadView(drawing: cellStore.selectedCell?.drawing)

Clean the project and compile it and preview the app. We can tap the drawing button, draw a picture and then save it.

Now, this drawing is huge. We could resize it with SwiftUI modifiers, but as an alternative, I’m going to show you how to render a smaller version of an image.

Model.swift

We’ll start in the model, again. Create a new computed property on Cell for the thumbnail. We’ll return an Image that we’ll create from the resized UIImage. Make sure that there is a drawing image. If there isn’t then just return nil.

var thumbnail: Image? {
  guard let drawing = self.drawing else {
    return nil
  }
}

Now, set up a scaled size:

let thumbnailSize = CGSize(width: drawing.size.width / 6,
                           height: drawing.size.height / 6)

And create the Image Renderer

let thumbnail = UIGraphicsImageRenderer(size: thumbnailSize).image { context in
  
}
return Image(uiImage: thumbnail)

Now we can just draw the image into the context, and return the image as a SwiftUI Image

drawing.draw(in: CGRect(origin: .zero, size: thumbnailSize))

We’ve got a thumbnail. We just need to display it in the cell.

CellView.swift

So back in CellView.swift. Just under CellView, open a new extension. Create a new View structure for the Cell thumbnail. Give it size and image properties to define the thumbnail.

extension CellView {
    struct Thumbnail: View {
      
      let size: CGSize
      let drawing: Image
    
      var body: some View {
        
      }
    }
}

And in the body, set up a ZStack to lay the drawing over the system’s current background color.

  ZStack {
    Color(uiColor: .systemBackground)
    drawing
      .resizable()
      .aspectRatio(contentMode: .fit)
      .frame(width: size.width, height: size.height)
  }

All we have to do now is use this little custom thumbnail view instead of the too-large Image we just put in the cell.

Thumbnail(size: cell.size, drawing: Image(uiImage: drawing))

To stop the thumbnail from leaking out over the side of the cell, we can clip it with the cell’s shape.

.clipShape(cell.shape.shape)

Go back to ContentView.swift and clean and build the project and make sure that it all works in the live preview.

Select a cell and go into the canvas. Draw something. Save it. And there is a nicely sized thumbnail image, cropped to the cell shape!