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

SwiftUI自定义AsyncImage如何为加载完成的Image添加修饰符

解决方案

核心结论

你当前的实现思路完全可行,无需单独传入ViewModifier,仅需要调整结构体的泛型定义、存储属性和初始化逻辑即可匹配你预期的调用方式。

调整说明

你原来的代码存在两处核心问题:

  • 泛型定义不符合需求,仅声明了一个Content泛型,无法同时匹配内容闭包和占位闭包的返回类型
  • 存储属性设计错误,不应该直接存储Content实例,而是要存储两个逃逸闭包,在图片加载完成后动态调用内容闭包生成带修饰符的视图

完整实现代码

import SwiftUI

struct CustomAsyncImageView<Content: View, Placeholder: View>: View {
    // 存储两个逃逸闭包
    private let content: (Image) -> Content
    private let placeholder: () -> Placeholder
    // 图片加载完成后需要触发视图刷新,所以用@State修饰
    @State private var image: Image?
    // 传入的dataKey,你可以按需替换为图片URL等其他参数
    private let dataKey: String
    
    public init(
        dataKey: String,
        @ViewBuilder content: @escaping (Image) -> Content,
        @ViewBuilder placeholder: @escaping () -> Placeholder
    ) {
        self.dataKey = dataKey
        self.content = content
        self.placeholder = placeholder
    }
    
    var body: some View {
        Group {
            if let image = image {
                // 加载完成时调用内容闭包,传入原生Image,返回用户加了修饰符的视图
                content(image)
            } else {
                // 加载中/加载失败展示占位
                placeholder()
            }
        }
        .onAppear(perform: loadImageWithAuth)
    }
    
    // 带鉴权的图片加载逻辑示例,你可以按需替换为自己的实现
    private func loadImageWithAuth() {
        guard let url = URL(string: "你的图片基础地址\(dataKey)") else { return }
        var request = URLRequest(url: url)
        // 在这里添加鉴权header,比如token
        request.setValue("Bearer 你的鉴权token", forHTTPHeaderField: "Authorization")
        
        URLSession.shared.dataTask(with: request) { data, _, error in
            guard let data = data, error == nil, let uiImage = UIImage(data: data) else { return }
            DispatchQueue.main.async {
                self.image = Image(uiImage: uiImage)
            }
        }.resume()
    }
}

调用验证

和你预期的调用方式完全一致:

CustomAsyncImageView(dataKey: dataKey) { image in    
     image
        .resizable()
        .scaledToFit()
} placeholder: {
     Rectangle()
        .fill(.gray.opacity(0.3))
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:18:03