HEIC Image Compression for iOS | raywenderlich.com

In this HEIC image compression tutorial, you’ll learn how to transform images into HEIC and JPEG formats, comparing their efficiency for optimum performance.

This is a companion discussion topic for the original entry at https://www.raywenderlich.com/4726843-heic-image-compression-for-ios

Thanks for the great tutorial!
I think there is a minor typo in the following sentence, HEIC image will be smaller:

Conversely, the HEIC image is larger but its compression is slower.

Thanks for letting me know. HEIC would not be a very good option if it was larger and slower. :sweat_smile:

Based on question from Twitter I wanted to briefly explain how to create an HEIC file that contains multiple images. I created a playground to see this in action, and it can be found here.

Note: In order for playgroundSharedDataDirectory to work properly you need to create the ~/Documents/Shared Playground Data/ directory manually. Xcode does not create this for you.

The key things to be aware of are:

  • Specifying the correct number of images when creating the destination CGImageDestinationCreateWithData.
  • Adding each image to the same destination using CGImageDestinationAddImage.
  • Completing the process using CGImageDestinationFinalize.

In the playground, I defined a method that creates HEIF compressed data which holds two images. Once the data is created and finalized the data is written to the share directory on your Mac. Opening this HEIC file in Preview.app will show both images that are contained in the file.


Here’s the method for those who don’t want to download the playground.

func createMultiImage(from names: [String], compressionQuality: CGFloat = 0.8) {
    let data = NSMutableData()
    guard let imageDestination = CGImageDestinationCreateWithData(
            data, AVFileType.heic as CFString, names.count, nil
        ) else {

    let options: NSDictionary = [
        kCGImageDestinationLossyCompressionQuality: compressionQuality

    names.compactMap({ UIImage(named: $0)?.cgImage }).forEach { cgImage in
        CGImageDestinationAddImage(imageDestination, cgImage, options)

    guard CGImageDestinationFinalize(imageDestination) else {

    let url = playgroundSharedDataDirectory.appendingPathComponent("combined01.heic")
    if data.write(to: url, atomically: true) {
        print("Wrote the file to: \(url)")

So how does one pronounce HEIC? I’m going with “Heck”! The I is silent and the “K” is implied. Let’s not have this GIF/JIFF debate :slight_smile:

I’m having error messages and crashes every 4 or 5 moves of a slider.
(iPhone X, iOS 13.1.2)


Like you would pronounce Heinz without ‘n’ maybe )

@naturaln0va Can you please help with this when you get a chance? Thank you - much appreciated! :]

I’ve tried this now on a couple versions of Xcode and it appears that cancelling operations in a queue works differently with iOS 13 and or Xcode 11. I recommend removing the continuous updates to the slider when running on device.

Here is the necessary change to make in viewDidLoad, replace the following:

#if targetEnvironment(simulator)
  action: #selector(sliderEndedTouch),
  for: [.touchUpInside, .touchUpOutside]
  action: #selector(sliderDidChange),
  for: .valueChanged

with this:

  action: #selector(sliderEndedTouch),
  for: [.touchUpInside, .touchUpOutside]

I hope this helps.

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!