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

SwiftUI加载UIImage数组横向显示无内容问题求助

SwiftUI多张横向图片加载无显示问题解决建议

核心问题分析

你的代码存在几个关键问题导致视图完全无显示:

  1. ImageLoader中images初始化为nil,调用append时无实际效果
  2. downloadImages函数中缓存命中后直接return,仅能加载第一张缓存图片
  3. Grid布局配置不合理,且用UIImage作为ForEach的id存在重复识别风险

具体修复步骤

1. 修复ImageLoader的数组初始化与加载逻辑

修改images的初始化方式,并移除downloadImages里错误的return语句:

class ImageLoader: ObservableObject {
    
    private static let imageCache = NSCache<AnyObject, AnyObject>()
    
    @Published var image: UIImage? = nil
    // 改为非可选空数组,确保append操作有效
    @Published var images: [UIImage] = []
    
    public func downloadImage(url: URL) {
        // 原单图加载逻辑保留不变
        let urlString = url.absoluteString
        
        if let imageFromCache = ImageLoader.imageCache.object(forKey: urlString as AnyObject) as? UIImage {
            self.image = imageFromCache
            return
        }
        
        URLSession.shared.dataTask(with: url) { (data, res, error) in
            guard let data = data, let image = UIImage(data: data) else {
                return
            }
            DispatchQueue.main.async { [weak self] in
                ImageLoader.imageCache.setObject(image, forKey: urlString  as AnyObject)
                self?.image = image
            }
        }.resume()
    }
    
    public func downloadImages(urls: [URL]) {
        for url in urls {
            let urlString = url.absoluteString
            
            if let imageFromCache = ImageLoader.imageCache.object(forKey: urlString as AnyObject) as? UIImage {
                self.images.append(imageFromCache)
                // 移除return,否则仅处理第一个缓存图片
                // return
            } else {
                URLSession.shared.dataTask(with: url) { (data, res, error) in
                    guard let data = data, let image = UIImage(data: data) else {
                        return
                    }
                    DispatchQueue.main.async { [weak self] in
                        ImageLoader.imageCache.setObject(image, forKey: urlString  as AnyObject)
                        self?.images.append(image)
                    }
                }.resume()
            }
        }
    }
}

2. 优化Logo视图的布局与ForEach标识

将Grid替换为更适合横向滚动的LazyHStack,并使用数组索引作为唯一标识(避免UIImage重复导致的识别问题):

struct PlatformLogoView: View { // 遵循Swift命名规范,首字母大写
    var platformLogos: [UIImage]
    
    var body: some View {
        LazyHStack(spacing: 10) { // 横向滚动容器,设置元素间距
            ForEach(platformLogos.indices, id: \.self) { index in
                let logo = platformLogos[index]
                Image(uiImage: logo)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(height: 30) // 固定高度,确保视图可见
                    .clipped()
                
                if index != platformLogos.count - 1 {
                    Divider() // 仅在非最后一个元素后显示分隔线
                }
            }
        }
        .border(.blue)
        .padding() // 增加内边距,让边框更明显
    }
}

3. 更新父视图的传递逻辑

由于images改为非可选数组,父视图直接传递即可:

@ObservedObject var logoLoader: ImageLoader = ImageLoader()
@ObservedObject var gameDetail: GameDetail = GameDetail()

var body: some View {
    VStack (alignment: .leading) {
        PlatformLogoView(platformLogos: logoLoader.images)
            .onAppear {
                if let logoURLs = gameDetail.game?.platformLogosUrls {
                    logoLoader.downloadImages(urls: logoURLs)
                }
            }
    }
}

额外注意点

  • Swift命名规范:结构体、类名需首字母大写(如platformLogoView改为PlatformLogoView)
  • 建议给网络请求添加错误处理,避免单张图片加载失败影响整体逻辑
  • 若需支持重新加载,可给ImageLoader添加清空数组的方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:48:12