【问题标题】:Show Image in a List from an URL在 URL 的列表中显示图像
【发布时间】:2019-11-06 00:52:39
【问题描述】:

我有一个从 JSON API 填充的列表。

ForEach(booksVM.books.sorted { $0.popularidad > $1.popularidad}) { book in
    HStack {
        Image(URL: book.imagen)
        Text(book.nombre)
        Spacer()
    }
    Text(book.autor)
    Spacer()
}

第三行是错误的,但这是我想要实现的。

现在,book.imagen 是 JSON 的所有图像 URL 的 Decodable 变量。我该怎么做?

JSON 以防万一:

[
{
    "id": 1,
    "nombre": "The design of every day things",
    "autor": "Don Norman",
    "disponibilidad": true,
    "popularidad": 70,
    "imagen": "https://images-na.ssl-images-amazon.com/images/I/410RTQezHYL._SX326_BO1,204,203,200_.jpg"
},
{
    "id": 2,
    "nombre": "100 años de soledad",
    "autor": "Garcia Marquez",
    "disponibilidad": false,
    "popularidad": 43,
    "imagen": "https://images-na.ssl-images-amazon.com/images/I/51egIZUl88L._SX336_BO1,204,203,200_.jpg"
}
]

和结构:

struct Book: Identifiable, Decodable {
    let id: Int
    let nombre: String
    let autor: String
    let disponibilidad: Bool
    let popularidad: Int
    let imagen: String
}

【问题讨论】:

标签: swiftui


【解决方案1】:

Here我找到了一个决定并为你修改了它。这个想法是用 ImageLoader 类创建 ImageView

struct ImageView: View {
    @ObservedObject var imageLoader:ImageLoader
    @State var image:UIImage = UIImage()

    func imageFromData(_ data:Data) -> UIImage {
        UIImage(data: data) ?? UIImage()
    }

    init(withURL url:String) {
        imageLoader = ImageLoader(urlString:url)
    }

    var body: some View {
        VStack {

            Image(uiImage: imageLoader.data != nil ? UIImage(data:imageLoader.data!)! : UIImage())
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width:100, height:100)
        }
    }

}

class ImageLoader: ObservableObject {
    @Published var dataIsValid = false
    var data:Data?

    init(urlString:String) {
        guard let url = URL(string: urlString) else { return }
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else { return }
            DispatchQueue.main.async {
                self.dataIsValid = true
                self.data = data
            }
        }
        task.resume()
    }
}

现在您可以将它用于您的列表:

struct ListView: View {
    let urls = ["https://images-na.ssl-images-amazon.com/images/I/410RTQezHYL._SX326_BO1,204,203,200_.jpg", "https://images-na.ssl-images-amazon.com/images/I/51egIZUl88L._SX336_BO1,204,203,200_.jpg"]

    var body: some View {
        List {
            ForEach(urls, id: \.self) { url in
                ImageView(withURL: url)
            }
        }
    }
}

这是预览结果:

【讨论】:

  • 哇!非常感谢!一个简单的问题,在列表部分,我如何将你拥有的 ForEach 的功能添加到我拥有的前一个功能中,我尝试使用 ImageView(withURL: book.imagen) 但不起作用。
  • @luwec,很难理解你有什么错误?您是指实时预览还是其他?
  • 我已经有一个 ForEach,您的解决方案添加了另一个 ForEach,这将创建另一个列表,我需要将您的 ForEach 与我的 ForEach 合并。
  • @luwec,你需要这样的东西吗? ForEach(books) { book inVStack {HStack {ImageView(withURL: book.imagen)Text(book.nombre)}Text(book.autor)Spacer()}}
猜你喜欢
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
  • 2020-10-07
相关资源
最近更新 更多