Skip to main content

Working with Images and Graphics

1. Loading Images

Example: Loading an Image from Bundle

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let image = UIImage(named: "sampleImage") {
            imageView.image = image
        }
    }
}
Property Description Notes
UIImage(named:) Initializes a UIImage object with the specified name from the main bundle. Looks for image files in the app's main bundle. Supports multiple image formats (PNG, JPEG, GIF, etc.).
UIImage(contentsOfFile:) Initializes a UIImage object with the image file at the specified path. Useful for loading images from custom locations or external storage.
UIImage(data:) Initializes a UIImage object with the image data provided. Useful when working with images received from network requests or other sources.
Note: Ensure image files are added to your Xcode project and included in the app bundle for UIImage(named:) to work correctly.
Warning: Loading large images directly into memory can cause performance issues or crashes. Consider using UIImage with UIImage.init(data:) and implementing lazy loading or image caching strategies.

2. Using SF Symbols

Symbol Name Description Notes
􀀁 photo.fill Filled photo icon Available in iOS 13+
􀁍 heart.fill Filled heart icon Available in iOS 13+
􀈤 gearshape.fill Filled gear shape icon Available in iOS 14+

Example: Using SF Symbols in UI

import UIKit

let imageView = UIImageView()
imageView.image = UIImage(systemName: "heart.fill")
imageView.tintColor = .red
Note: SF Symbols are scalable and support dynamic color rendering.

3. Resizing Images

Example: Resize Image to Fit Within Bounds

import UIKit

func resizeImage(_ image: UIImage, toMaxSize maxSize: CGSize) -> UIImage? {
    guard let cgImage = image.cgImage else { return nil }
    
    let imageWidth = CGFloat(cgImage.width)
    let imageHeight = CGFloat(cgImage.height)
    
    let scale = min(maxSize.width / imageWidth, maxSize.height / imageHeight)
    let newSize = CGSize(width: imageWidth * scale, height: imageHeight * scale)
    
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
    defer { UIGraphicsEndImageContext() }
    
    image.draw(in: CGRect(origin: .zero, size: newSize))
    
    return UIGraphicsGetImageFromCurrentImageContext()
}

// Usage
let originalImage = UIImage(named: "sample.jpg")!
let resizedImage = resizeImage(originalImage, toMaxSize: CGSize(width: 300, height: 300))
Property Description Notes
UIImage Class for handling images in iOS Can be initialized from file, data, or asset catalog
cgImage Core Graphics image representation Used for low-level image manipulation
draw(in:) Draws image into a context Used for resizing and transformations
Note: When resizing, maintain aspect ratio to prevent distortion.
Warning: Resizing large images can cause memory issues. Consider using UIImage.init(data:) with compressed data for better performance.

4. Cropping Images

Example: Cropping a UIImage

import UIKit

let image = UIImage(named: "sampleImage")!
let cropRect = CGRect(x: 50, y: 50, width: 200, height: 200)
let croppedImage = image.cgImage?.cropping(to: cropRect)
let finalImage = UIImage(cgImage: croppedImage!)
Property Description Notes
cgImage Core Graphics image representation Used for cropping operations
cropping(to:) Method to crop image to specified rectangle Returns optional CGImage
CGRect Rectangle defining crop area Specify x, y, width, height
Note: Cropping operations are performed on the cgImage property, not directly on UIImage.

5. Applying Image Filters

Filter Description Usage Example
CIColorControls Adjusts brightness, contrast, and saturation of an image. let filter = CIFilter(name: "CIColorControls")<br>filter?.setValue(inputImage, forKey: kCIInputImageKey)<br>filter?.setValue(1.2, forKey: kCIInputBrightnessKey)<br>filter?.setValue(1.5, forKey: kCIInputSaturationKey)
CIGaussianBlur Applies a Gaussian blur to an image. let filter = CIFilter(name: "CIGaussianBlur")<br>filter?.setValue(inputImage, forKey: kCIInputImageKey)<br>filter?.setValue(5.0, forKey: kCIInputRadiusKey)
CIPhotoEffectProcess Applies a photo effect filter to an image. let filter = CIFilter(name: "CIPhotoEffectProcess")<br>filter?.setValue(inputImage, forKey: kCIInputImageKey)

Example: Applying a Blur Filter

import UIKit<br>import CoreImage<br><br>class ImageFilterViewController: UIViewController {<br>&nbsp;&nbsp;@IBOutlet weak var imageView: UIImageView!<br><br>&nbsp;&nbsp;func applyBlurEffect(to image: UIImage) -> UIImage? {<br>&nbsp;&nbsp;&nbsp;&nbsp;let context = CIContext()<br>&nbsp;&nbsp;&nbsp;&nbsp;guard let ciImage = CIImage(image: image) else { return nil }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;let filter = CIFilter(name: "CIGaussianBlur")<br>&nbsp;&nbsp;&nbsp;&nbsp;filter?.setValue(ciImage, forKey: kCIInputImageKey)<br>&nbsp;&nbsp;&nbsp;&nbsp;filter?.setValue(10.0, forKey: kCIInputRadiusKey)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;guard let outputImage = filter?.outputImage else { return nil }<br>&nbsp;&nbsp;&nbsp;&nbsp;return UIImage(ciImage: context.createCGImage(outputImage, from: outputImage.extent)!)<br>&nbsp;&nbsp;}<br>}

6. Drawing with Core Graphics

Example: Basic Drawing Context

import UIKit

class DrawingView: UIView {
    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // Set fill color
        context.setFillColor(UIColor.blue.cgColor)
        
        // Draw a rectangle
        context.fill(CGRect(x: 10, y: 10, width: 100, height: 100))
    }
}
Method Description Notes
UIGraphicsGetCurrentContext() Retrieves the current graphics context Must be called within a draw method
setFillColor(_:) Sets the fill color for subsequent drawing Accepts CGColor or UIColor
fill(_:) Fills a rectangle with the current fill color Uses CGRect for positioning
Note: Core Graphics operations are performed in the coordinate system where (0,0) is at the top-left corner of the view.

7. Using UIGraphicsImageRenderer

Example: Creating a Simple Image with UIGraphicsImageRenderer

import UIKit

let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))
let image = renderer.image { context in
    let rect = CGRect(x: 0, y: 0, width: 200, height: 200)
    UIColor.blue.setFill()
    context.fill(rect)
    
    let circlePath = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100))
    UIColor.red.setFill()
    circlePath.fill()
}

// Use the image in an UIImageView
let imageView = UIImageView(image: image)
Property Description Example
size The size of the image to be rendered CGSize(width: 200, height: 200)
scale The scale factor for the image (default is screen scale) 2.0
format The image format to use (e.g., PNG, JPEG) UIGraphicsImageRendererFormat()
Note: UIGraphicsImageRenderer is preferred over UIGraphicsBeginImageContext for creating images in modern iOS development.
Warning: Ensure that the context is properly managed to avoid memory leaks.

Key Features of UIGraphicsImageRenderer

  • Thread-safe rendering
  • Automatic handling of scale and graphics context
  • Supports multiple image formats
  • Efficient memory usage

8. Creating Custom Drawing in UIView

Example: Custom Drawing in UIView

import UIKit

class CustomDrawingView: UIView {
    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // Draw a circle
        let circlePath = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100))
        UIColor.blue.setFill()
        circlePath.fill()
        
        // Draw a line
        context.move(to: CGPoint(x: 20, y: 20))
        context.addLine(to: CGPoint(x: 180, y: 180))
        context.setStrokeColor(UIColor.red.cgColor)
        context.setLineWidth(3)
        context.strokePath()
    }
}
Method Description Notes
draw(_ rect: CGRect) Override this method to perform custom drawing Called by the system when the view needs to redraw
UIGraphicsGetCurrentContext() Gets the current graphics context Must be called inside draw(_:) to access the drawing context
Note: Custom drawing in UIView is performed using Core Graphics (Quartz 2D). Always call UIGraphicsGetCurrentContext() to get the current graphics context before drawing.
Warning: Do not call setNeedsDisplay() from within the draw(_:) method, as it will cause an infinite loop.

9. Working with Image Assets

Example: Adding an Image Asset to Xcode

// In your ViewController.swift
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Load image from asset catalog
        imageView.image = UIImage(named: "customImage")
    }
}
Property Description Usage
UIImage(named:) Initializes a UIImage object with the specified asset name let image = UIImage(named: "myImage")
UIImage.init(contentsOfFile:) Initializes a UIImage object from the file at the specified path let image = UIImage(contentsOfFile: filePath)
UIImage.init(data:) Initializes a UIImage object from the specified data let image = UIImage(data: imageData)
Note: Image assets should be added to the asset catalog in Xcode for optimal performance and automatic scaling.
Warning: Avoid loading large images directly from files or data, as this can cause memory issues.

Image Asset Best Practices

  • Use asset catalogs for all image assets
  • Provide multiple resolutions (1x, 2x, 3x) for each image
  • Use appropriate image formats (PNG, JPEG, GIF, SVG)
  • Optimize image sizes to reduce app bundle size

10. Supporting Dark Mode Images

Property Values Description
UIImage UIImage Image representation in iOS
UIImageAsset UIImageAsset Asset that can provide different images based on traits
UIImage.preferredColorScheme .light, .dark Color scheme preference for image rendering

Example: Using Image Assets for Dark Mode

let image = UIImage&#40;named: "icon"&#41;
let imageAsset = UIImageAsset&#40;named: "icon"&#41;
let darkModeImage = imageAsset.image&#40;for: UITraitCollection&#40;userInterfaceStyle: .dark&#41;&#41;
Note: Ensure image assets are properly configured in Asset Catalog with appropriate light/dark variants.
Warning: Using UIImage directly without trait collections may not respect dark mode settings.

11. Handling Image Caching

Example: Basic Image Caching with NSCache

import UIKit

class ImageCache {
    static let shared = ImageCache()
    private let cache = NSCache<NSString, UIImage>()

    private init() {
        cache.countLimit = 50
        cache.totalCostLimit = 100 * 1024 * 1024 // 100 MB
    }

    func image(forKey key: String) -> UIImage? {
        return cache.object(forKey: key as NSString)
    }

    func setImage(_ image: UIImage, forKey key: String) {
        cache.setObject(image, forKey: key as NSString)
    }
}

// Usage
let cachedImage = ImageCache.shared.image(forKey: "profile_123")
if let image = cachedImage {
    // Use cached image
} else {
    // Load and cache image
    ImageCache.shared.setImage(image, forKey: "profile_123")
}
Property Description Notes
cache.countLimit Maximum number of objects to store in cache Defaults to Int.max
cache.totalCostLimit Maximum total cost of all cached objects In bytes, defaults to Int.max
cache.object(forKey:) Retrieves an object from cache Returns nil if not found
cache.setObject(_:forKey:) Stores an object in cache Automatically evicts old entries if limits exceeded
Note: NSCache is thread-safe and automatically manages memory pressure.
Warning: Avoid caching large images without size limits to prevent memory issues.

Was this article helpful?