You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS18适配:Swift用UIGraphicsImageRenderer实现UIImage圆形缩放裁剪

iOS 18适配:用UIGraphicsImageRenderer重构圆形图片缩放裁剪功能

iOS 18 开始UIGraphicsBeginImageContextWithOptions、UIGraphicsGetCurrentContext、UIGraphicsEndImageContext这三个API被标记为废弃,原有基于这些API实现的图片圆形缩放裁剪代码会崩溃,需要改用UIGraphicsImageRenderer完成相同功能。


原有废弃API实现代码

func scaleCropAndCircleImage(image:UIImage, frame:CGRect) throws -> UIImage {
    
    enum FunctionError: Error {
        case nilContext
        case nilImage
    }
    
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(frame.size.width, frame.size.height), false, 0.0)
    guard let context = UIGraphicsGetCurrentContext() else { throw FunctionError.nilContext }
    
    // width and heights of passed values of uiimage and CGRect
    let passedimageWidth = image.size.width
    let passedimageHeight = image.size.height
    let passedrectWidth = frame.size.width
    let passedrectHeight = frame.size.height
    
    // scale factor calculation
    let scaleFactorX = passedrectWidth/passedimageWidth
    let scaleFactorY = passedrectHeight/passedimageHeight
    
    // centre of the circle calculation
    let imageCentreX = passedrectWidth/2
    let imageCentreY = passedrectHeight/2
    
    // Creating and clipping to a CIRCULAR Path
    let radius = passedrectWidth/2
    context.beginPath()
    context.addArc(center: CGPoint(x: imageCentreX, y: imageCentreY), radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: false)
    context.closePath()
    context.clip()
    
    //Seting  the scaling factor for graphics context
    context.scaleBy(x: scaleFactorX, y: scaleFactorY)
    

    let myRect:CGRect = CGRectMake(0, 0, passedimageWidth, passedimageHeight)
    image.draw(in: myRect)
    
    let newCroppedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    guard let newCroppedImage else { throw FunctionError.nilImage }
    
    return newCroppedImage
}

未完成的改写尝试

import UIKit

extension UIImage {
    func roundedCornerImage(with radius: CGFloat) -> UIImage {
        let format = UIGraphicsImageRendererFormat()
        format.scale = scale
        let renderer = UIGraphicsImageRenderer(size: size, format: format)
        return renderer.image { rendererContext in
            let rect = CGRect(origin: .zero, size: size)
            let path = UIBezierPath(roundedRect: rect,
                                    byRoundingCorners: .allCorners,
                                    cornerRadii: CGSize(width: radius, height: radius))
            path.close()

            let cgContext = rendererContext.cgContext
            cgContext.saveGState()
            path.addClip()
            draw(in: rect)
            cgContext.restoreGState()
        }
    }
}

完整重构实现

func scaleCropAndCircleImage(image: UIImage, frame: CGRect) throws -> UIImage {
    enum FunctionError: Error {
        case nilImage
    }
    
    let targetSize = frame.size
    let format = UIGraphicsImageRendererFormat()
    // 对应原代码中0.0的scale参数,使用当前屏幕缩放比例
    format.scale = 0.0
    let renderer = UIGraphicsImageRenderer(size: targetSize, format: format)
    
    let resultImage = renderer.image { rendererContext in
        let cgContext = rendererContext.cgContext
        
        // 沿用原逻辑计算缩放因子
        let imageWidth = image.size.width
        let imageHeight = image.size.height
        let scaleFactorX = targetSize.width / imageWidth
        let scaleFactorY = targetSize.height / imageHeight
        
        // 创建圆形裁剪路径,和原逻辑完全一致
        let center = CGPoint(x: targetSize.width / 2, y: targetSize.height / 2)
        let radius = targetSize.width / 2
        cgContext.beginPath()
        cgContext.addArc(center: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: false)
        cgContext.closePath()
        cgContext.clip()
        
        // 缩放上下文,匹配原逻辑
        cgContext.scaleBy(x: scaleFactorX, y: scaleFactorY)
        
        // 绘制原图
        let imageRect = CGRect(origin: .zero, size: image.size)
        image.draw(in: imageRect)
    }
    
    guard resultImage != nil else { throw FunctionError.nilImage }
    return resultImage
}

重构关键点说明

  • 用UIGraphicsImageRenderer替代手动上下文管理,无需手动开启/关闭上下文
  • 完全保留原有的缩放因子计算、圆形裁剪逻辑,确保最终效果和旧代码一致
  • 移除了nilContext错误分支:UIGraphicsImageRenderer会自动处理上下文创建,不会出现上下文为空的情况
  • format.scale = 0.0对应原API的第三个参数,保证生成图片的清晰度匹配屏幕

内容的提问来源于stack exchange,提问作者user37511008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:28:11