Article / 2026/05/29

Swift UIGraphicsImageRenderer

UIGraphicsImageRenderer 是 iOS 10+ 中引入的现代图形渲染类,用于替代传统的 UIGraphicsBeginImageContext 系列函数。它提供了更高效、内存安全的图像渲染功能,支持广色域和自动处理...

🚀 Swift UIGraphicsImageRenderer 完整 API 指南

概述

UIGraphicsImageRenderer 是 iOS 10+ 中引入的现代图形渲染类,用于替代传统的 UIGraphicsBeginImageContext 系列函数。它提供了更高效、内存安全的图像渲染功能,支持广色域和自动处理不同的设备分辨率。

核心类介绍

UIGraphicsImageRenderer

主要的图像渲染器类,负责创建和管理图像绘制上下文。

UIGraphicsImageRendererFormat

用于配置渲染器的格式设置类。

UIGraphicsImageRendererContext

绘制上下文类,提供绘制操作的环境。


UIGraphicsImageRenderer API

初始化方法

init(size: CGSize)

创建指定尺寸的图像渲染器。

let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))

init(size: CGSize, format: UIGraphicsImageRendererFormat)

创建指定尺寸和格式的图像渲染器。

let format = UIGraphicsImageRendererFormat()
format.scale = 2.0
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200), format: format)

init(bounds: CGRect)

根据边界矩形创建图像渲染器。

let bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
let renderer = UIGraphicsImageRenderer(bounds: bounds)

init(bounds: CGRect, format: UIGraphicsImageRendererFormat)

根据边界矩形和格式创建图像渲染器。

let format = UIGraphicsImageRendererFormat()
let bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
let renderer = UIGraphicsImageRenderer(bounds: bounds, format: format)

属性

format: UIGraphicsImageRendererFormat (只读)

获取渲染器使用的格式。

let format = renderer.format
print("Scale: \(format.scale)")

allowsImageOutput: Bool (只读)

指示渲染器是否允许图像输出。

if renderer.allowsImageOutput {
    // 可以进行图像渲染
}

图像生成方法

image(actions: (UIGraphicsImageRendererContext) -> Void) -> UIImage

执行绘制操作并返回生成的图像。

let image = renderer.image { context in
    // 绘制代码
    UIColor.red.setFill()
    context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
}

pngData(actions: (UIGraphicsImageRendererContext) -> Void) -> Data

执行绘制操作并返回 PNG 格式的数据。

let pngData = renderer.pngData { context in
    // 绘制代码
    UIColor.blue.setFill()
    context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
}

jpegData(withCompressionQuality: CGFloat, actions: (UIGraphicsImageRendererContext) -> Void) -> Data

执行绘制操作并返回 JPEG 格式的数据。

let jpegData = renderer.jpegData(withCompressionQuality: 0.8) { context in
    // 绘制代码
    UIColor.green.setFill()
    context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
}

UIGraphicsImageRendererFormat API

类方法

default() -> UIGraphicsImageRendererFormat

返回默认格式。

let defaultFormat = UIGraphicsImageRendererFormat.default()

preferred() -> UIGraphicsImageRendererFormat

返回当前设备的首选格式。

let preferredFormat = UIGraphicsImageRendererFormat.preferred()

初始化方法

init()

创建默认格式实例。

let format = UIGraphicsImageRendererFormat()

init(for traitCollection: UITraitCollection)

根据特征集合创建格式。

let traitCollection = UITraitCollection(displayScale: 3.0)
let format = UIGraphicsImageRendererFormat(for: traitCollection)

属性

scale: CGFloat

设置或获取渲染比例。

format.scale = 2.0  // 设置为 2x 分辨率

opaque: Bool

设置或获取是否为不透明渲染。

format.opaque = true  // 不透明渲染,性能更好

prefersExtendedRange: Bool

设置或获取是否使用扩展颜色范围。

format.prefersExtendedRange = true  // 支持 P3 广色域

preferredRange: UIGraphicsImageRendererFormat.Range (只读)

获取首选的颜色范围。

let range = format.preferredRange
switch range {
case .automatic:
    print("自动选择")
case .extended:
    print("扩展颜色范围")
case .standard:
    print("标准颜色范围")
@unknown default:
    print("未知范围")
}

UIGraphicsImageRendererContext API

属性

cgContext: CGContext

获取底层的 Core Graphics 上下文。

let cgContext = context.cgContext
cgContext.setLineCap(.round)

format: UIGraphicsImageRendererFormat

获取渲染格式。

let format = context.format

currentImage: UIImage

获取当前渲染的图像。

let currentImage = context.currentImage

绘制方法

fill(_: CGRect)

填充指定矩形区域。

context.fill(CGRect(x: 10, y: 10, width: 50, height: 50))

fill(_: CGRect, blendMode: CGBlendMode)

使用指定混合模式填充矩形。

context.fill(CGRect(x: 10, y: 10, width: 50, height: 50), blendMode: .multiply)

stroke(_: CGRect)

描边指定矩形。

context.stroke(CGRect(x: 10, y: 10, width: 50, height: 50))

stroke(_: CGRect, blendMode: CGBlendMode)

使用指定混合模式描边矩形。

context.stroke(CGRect(x: 10, y: 10, width: 50, height: 50), blendMode: .overlay)

clip(to: CGRect)

设置裁剪区域。

context.clip(to: CGRect(x: 0, y: 0, width: 100, height: 100))

实际应用示例

基础绘制示例

func createSimpleImage() -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))
    
    let image = renderer.image { context in
        // 设置背景色
        UIColor.lightGray.setFill()
        context.fill(CGRect(x: 0, y: 0, width: 200, height: 200))
        
        // 绘制红色圆形
        UIColor.red.setFill()
        let circleRect = CGRect(x: 50, y: 50, width: 100, height: 100)
        context.cgContext.fillEllipse(in: circleRect)
        
        // 绘制蓝色边框
        UIColor.blue.setStroke()
        context.cgContext.setLineWidth(3.0)
        context.stroke(CGRect(x: 25, y: 25, width: 150, height: 150))
    }
    
    return image
}

高级绘制示例

func createGradientImage() -> UIImage {
    let format = UIGraphicsImageRendererFormat()
    format.scale = 0  // 使用设备原生分辨率
    format.opaque = false
    
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 300, height: 200), format: format)
    
    let image = renderer.image { context in
        let cgContext = context.cgContext
        
        // 创建渐变
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
        let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: nil)!
        
        // 绘制线性渐变
        cgContext.drawLinearGradient(gradient, 
                                   start: CGPoint(x: 0, y: 0), 
                                   end: CGPoint(x: 300, y: 200), 
                                   options: [])
        
        // 添加文本
        let text = "Hello, UIGraphicsImageRenderer!"
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 20),
            .foregroundColor: UIColor.white
        ]
        
        let textSize = text.size(withAttributes: attributes)
        let textRect = CGRect(x: (300 - textSize.width) / 2, 
                            y: (200 - textSize.height) / 2, 
                            width: textSize.width, 
                            height: textSize.height)
        
        text.draw(in: textRect, withAttributes: attributes)
    }
    
    return image
}

图像合成示例

func combineImages(_ image1: UIImage, _ image2: UIImage) -> UIImage {
    let size = CGSize(width: max(image1.size.width, image2.size.width),
                     height: max(image1.size.height, image2.size.height))
    
    let renderer = UIGraphicsImageRenderer(size: size)
    
    let combinedImage = renderer.image { context in
        // 绘制第一张图片
        image1.draw(at: .zero)
        
        // 使用混合模式绘制第二张图片
        image2.draw(at: CGPoint(x: 50, y: 50), blendMode: .multiply, alpha: 0.7)
    }
    
    return combinedImage
}

生成数据格式示例

func generateImageData() {
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 100, height: 100))
    
    // 生成 PNG 数据
    let pngData = renderer.pngData { context in
        UIColor.red.setFill()
        context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
    }
    
    // 生成 JPEG 数据
    let jpegData = renderer.jpegData(withCompressionQuality: 0.8) { context in
        UIColor.blue.setFill()
        context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
    }
    
    // 保存到文件
    let documentsPath = FileManager.default.urls(for: .documentDirectory, 
                                               in: .userDomainMask)[0]
    
    try? pngData.write(to: documentsPath.appendingPathComponent("image.png"))
    try? jpegData.write(to: documentsPath.appendingPathComponent("image.jpg"))
}

最佳实践

1. 选择合适的格式

// 对于不透明图像,设置 opaque = true 以提高性能
let format = UIGraphicsImageRendererFormat()
format.opaque = true

// 对于需要广色域的图像
format.prefersExtendedRange = true

2. 合理设置分辨率

// 使用设备原生分辨率
format.scale = 0

// 或明确指定分辨率
format.scale = UIScreen.main.scale

3. 内存管理

// 对于大图像,考虑分块处理
func processLargeImage() {
    autoreleasepool {
        let renderer = UIGraphicsImageRenderer(size: largeSize)
        let image = renderer.image { context in
            // 绘制操作
        }
        // 使用图像
    }
}

4. 错误处理

func safeImageGeneration() -> UIImage? {
    guard UIGraphicsImageRenderer.allowsImageOutput else {
        print("图像输出不被允许")
        return nil
    }
    
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 100, height: 100))
    return renderer.image { context in
        // 绘制操作
    }
}

与传统 API 的对比

传统方式 (已废弃)

UIGraphicsBeginImageContextWithOptions(size, false, 0)
// 绘制代码
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

现代方式 (推荐)

let renderer = UIGraphicsImageRenderer(size: size)
let image = renderer.image { context in
    // 绘制代码
}

总结

UIGraphicsImageRenderer 提供了现代、高效的图像渲染解决方案,具有以下优势:

  • 自动内存管理:无需手动管理图像上下文
  • 设备适配:自动处理不同设备的分辨率
  • 广色域支持:支持 P3 等广色域显示
  • 更好的性能:优化的渲染流程
  • 类型安全:Swift 原生 API,减少错误

建议在所有新项目中使用 UIGraphicsImageRenderer 替代传统的 UIGraphicsBeginImageContext 系列函数。

Giscus 未启用:请在 src/site.config.ts 中配置 repoId 与 categoryId。