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

使用ImageRenderer渲染时缺失弧形文本,是否为Xcode Bug?

问题:ImageRenderer导出图片缺失CrookedText生成的弧形文本

我使用CrookedText库生成环绕圆形的弧形文本,通过ImageRenderer生成图片用于导出时,生成的图片中缺失该弧形文本,但相同的CardView在屏幕上可正常显示。当前导出结果(上方图片)与预期输出(下方图片)对比见附图。相关代码如下:

struct CardPresenterView: View {
    
    @State private var renderedImage = Image(systemName: "photo")
    
    var body: some View {
        VStack() {
            Spacer()
            OptionView()
            Spacer()
            renderedImage
                .shadow(radius: 10)
            Spacer()
            CardView()
               .aspectRatio(2/3, contentMode: .fit)
            
           Spacer()
               ShareLink("Export", item: renderedImage, preview: SharePreview(Text("Shared image"), image: renderedImage))
        }
        .onAppear { render() }
    }
    
    @MainActor func render() {
         let renderer = ImageRenderer(content: CardView().aspectRatio(2/3, contentMode: .fit))
         if let uiImage = renderer.uiImage {
             renderedImage = Image(uiImage: uiImage)
         }
     }
}

解答

这大概率不是Xcode的Bug,而是CrookedText的渲染逻辑与ImageRenderer的工作机制不兼容导致的。

可能的原因:

  • CrookedText可能依赖UIKit的实时渲染上下文(比如UIGraphicsGetCurrentContext()),而ImageRenderer是在离线上下文里执行渲染,部分第三方库的自定义渲染逻辑未适配这种离线场景。
  • 部分文本渲染库会采用异步绘制或依赖视图层级的实时状态,ImageRenderer在快照时可能未等待这些异步绘制操作完成就生成了图片。

可行的解决办法:

  1. 强制同步合成渲染:给CardView添加.drawingGroup()修饰符,让SwiftUI先将视图内容合成到位图上下文,再交由ImageRenderer处理:
@MainActor func render() {
     let renderer = ImageRenderer(content: CardView()
         .aspectRatio(2/3, contentMode: .fit)
         .drawingGroup())
     if let uiImage = renderer.uiImage {
         renderedImage = Image(uiImage: uiImage)
     }
 }
  1. 延迟执行渲染:如果CrookedText存在异步绘制逻辑,可在render()方法中延迟执行渲染操作,确保弧形文本绘制完成:
@MainActor func render() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        let renderer = ImageRenderer(content: CardView().aspectRatio(2/3, contentMode: .fit))
        if let uiImage = renderer.uiImage {
            renderedImage = Image(uiImage: uiImage)
        }
    }
}
  1. 替换为UIView快照方式:若上述方法无效,可尝试将CardView转为UIHostingController,再对其视图进行快照,替代ImageRenderer的使用:
@MainActor func render() {
    let hostingController = UIHostingController(rootView: CardView().aspectRatio(2/3, contentMode: .fit))
    hostingController.view.frame = CGRect(x: 0, y: 0, width: 300, height: 450) // 设置合适的尺寸
    hostingController.view.layoutIfNeeded()
    
    let renderer = UIGraphicsImageRenderer(size: hostingController.view.bounds.size)
    let uiImage = renderer.image { context in
        hostingController.view.drawHierarchy(in: hostingController.view.bounds, afterScreenUpdates: true)
    }
    
    renderedImage = Image(uiImage: uiImage)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:55:55