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

Swift中UIImage需触发两次才加载的问题求助

解决SwiftUI中fullScreenCover首次无法显示图片的问题

问题根源

你遇到的问题是状态更新时机不匹配:设置displayedImage后立刻将showingImage设为true,SwiftUI的状态更新是异步的,弹窗初始化时displayedImage的更新还未完成,导致首次弹窗里的可选绑定失败。第二次点击时displayedImage已有缓存值,因此能正常显示。

最优解决方案

用fullScreenCover(item:)替代isPresented:绑定,将图片状态和弹窗显示状态合并,确保弹窗出现时图片已准备就绪。

修改后的代码

  1. 替换原有的两个@State变量:
// 移除这两个变量
// @State private var displayedImage: UIImage?
// @State private var showingImage: Bool = false

// 改用单个可选状态变量
@State private var presentedImage: UIImage?
  1. 更新按钮和fullScreenCover代码:
Button("Show Image") {
    if let insuranceCardData = vehicle.insuranceCard {
        // 直接赋值,触发弹窗
        presentedImage = UIImage(data: insuranceCardData)
        print("Button - Image ready: \(presentedImage != nil)")
    }
}
.foregroundColor(.white)
.padding()
.background(Color.green)
.cornerRadius(10)
.padding()

// 使用item绑定的fullScreenCover
.fullScreenCover(item: $presentedImage) { image in
    Image(uiImage: image)
        .resizable()
        .scaledToFit()
        .onTapGesture {
            presentedImage = nil // 关闭弹窗
        }
}

为什么这个方案有效

fullScreenCover(item:)会在presentedImage从nil变为非nil时自动显示弹窗,且弹窗的内容会直接使用最新的image值,完全避免了状态更新不同步的问题。相比isPresented:,这种方式更符合SwiftUI的状态驱动设计理念。

其他可选方案(不推荐)

如果坚持使用isPresented:,可以通过延迟触发弹窗确保状态更新完成,但这种方式依赖时间延迟,稳定性较差:

Button("Show Image") {
    if let insuranceCardData = vehicle.insuranceCard {
        displayedImage = UIImage(data: insuranceCardData)
        // 延迟极短时间后触发弹窗
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
            showingImage = true
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:55:02