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> @IBOutlet weak var imageView: UIImageView!<br><br> func applyBlurEffect(to image: UIImage) -> UIImage? {<br> let context = CIContext()<br> guard let ciImage = CIImage(image: image) else { return nil }<br><br> let filter = CIFilter(name: "CIGaussianBlur")<br> filter?.setValue(ciImage, forKey: kCIInputImageKey)<br> filter?.setValue(10.0, forKey: kCIInputRadiusKey)<br><br> guard let outputImage = filter?.outputImage else { return nil }<br> return UIImage(ciImage: context.createCGImage(outputImage, from: outputImage.extent)!)<br> }<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(named: "icon")
let imageAsset = UIImageAsset(named: "icon")
let darkModeImage = imageAsset.image(for: UITraitCollection(userInterfaceStyle: .dark))
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.