Skip to content

Instantly share code, notes, and snippets.

@Codelaby
Last active October 22, 2024 13:53
Show Gist options
  • Save Codelaby/e5dd4aaefed37a8741f932b92d5073d4 to your computer and use it in GitHub Desktop.
Save Codelaby/e5dd4aaefed37a8741f932b92d5073d4 to your computer and use it in GitHub Desktop.
Prefetch big images
struct RemotePhotoDemoModel: Identifiable {
let id: UUID = .init()
let image: String
var imageData: Data?
static let allPhotos: [RemotePhotoDemoModel] = [
//RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1531737212413-667205e1cda"), // error sample
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1510001618818-4b4e3d86bf0f"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1504284992506-f6d82d0f2f2a"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1465447142348-e9952c393450"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1675826460422-e39481fae224"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661964121314-cb43af3580a1"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1514920735211-8c697444a248"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1547981609-4b6bfe67ca0b"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1517309230475-6736d926b979"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1510423579098-f47bf52b6764"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1474181487882-5abf3f0ba6c2"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1508804052814-cd3ba865a116"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661962892760-5e50359c5123"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1529020503594-28b8a4f004bd"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1528163186890-de9b86b54b51"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1465935607384-d6a9087be24a"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1520745947248-e287a72ed646"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1517248980687-80aa4dfd5218"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1508043157312-69e4bf3dd28c"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1531981462953-7cea7af328e0"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1603384446936-5646a2481a36"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1542554250-726628a42330"),
RemotePhotoDemoModel(image: "https://cdn.pixabay.com/photo/2020/05/29/04/28/chinese-5233524_1280.jpg"),
RemotePhotoDemoModel(image: "https://cdn.pixabay.com/photo/2016/07/20/05/14/wulingyuan-1529632_1280.jpg"),
RemotePhotoDemoModel(image: "https://cdn.pixabay.com/photo/2017/08/14/07/37/china-2639590_1280.jpg"),
RemotePhotoDemoModel(image: "https://cdn.pixabay.com/photo/2015/03/19/10/43/china-680715_1280.jpg"),
RemotePhotoDemoModel(image: "https://cdn.pixabay.com/photo/2022/03/26/14/54/chongqing-7093033_1280.jpg"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1524413840807-0c3cb6fa808d"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1542051841857-5f90071e7989"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1545569341-9eb8b30979d9"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1540959733332-eab4deabeeaf"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1528181304800-259b08848526"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1506665531195-3566af2b4dfa"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1519915247718-1703f9c6bb15"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661962958462-9e52fda9954d"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1531169628939-e84f860fa5d6"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1673288456074-ef3c61ca27f4"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661854008793-8ce54b2e622b"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1504457047772-27faf1c00561"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1504699439244-a7e34870c35d"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1559592413-7cec4d0cae2b"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1516484681091-7d83961805f4"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/flagged/photo-1549874613-8ea0adee1a82"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1712455498779-2a82e9d4b41a"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661963095864-01a3dbb82d90"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661916287718-edb15703cbaf"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1641573337436-90557fdd9604"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1552058185-28aa65f3bbaf"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1465056836041-7f43ac27dcb5"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1507699622108-4be3abd695ad"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1462759353907-b2ea5ebd72e7"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1523049820105-c2e73204bac1"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1494500764479-0c8f2919a3d8"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1618811213393-5f399dab320e"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1695197974761-431794d2a415"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1713945305643-89f7b4cbc076"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1715229001649-d6fbb422fa1a"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1729299960640-f56dac79d34e"),
RemotePhotoDemoModel(image: "https://images.unsplash.com/photo-1623253436564-5786debfccad"),
RemotePhotoDemoModel(image: "https://plus.unsplash.com/premium_photo-1661882377491-c5685537447f")
]
}
import SwiftUI
import Nuke //https://github.com/kean/Nuke
@MainActor
@Observable
class RemotePhotoViewModel {
var photos: [RemotePhotoDemoModel] = []
private let pipeline = ImagePipeline.shared
init() {
self.photos = RemotePhotoDemoModel.allPhotos
}
func downloadImage(for photo: RemotePhotoDemoModel) async throws {
print("⬇️ downloadImage", photo.image)
guard let index = self.photos.firstIndex(where: { $0.id == photo.id }) else { return }
let request = ImageRequest(
url: URL(string: photo.image)!,
processors: [.resize(width: 320)],
priority: .high
)
let image = try await pipeline.image(for: request)
if let imageData = image.pngData() {
self.photos[index].imageData = imageData
let sizeInBytes = imageData.count
print("✅ downloadImage", photo.image, "Size: \(sizeInBytes) bytes", "set index \(index)")
} else {
print("⚠️ downloadImage", photo.image, "Failed to convert image to PNG data")
}
}
}
struct ScrollWithRemoteImages: View {
@State private var viewModel = RemotePhotoViewModel()
var body: some View {
let _ = Self._printChanges()
ScrollView(.vertical) {
LazyVStack {
ForEach(viewModel.photos, id: \.id) { photo in
VStack {
if let imageData = photo.imageData, let image = UIImage(data: imageData) {
photoView(image: Image(uiImage: image))
} else {
VStack {
Spacer()
ProgressView()
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.regularMaterial)
.aspectRatio(4 / 3, contentMode: .fit)
.onAppear {
Task {
try await viewModel.downloadImage(for: photo)
}
}
}
}
.id(photo.id)
}
}
.scrollTargetLayout()
}
}
@ViewBuilder
private func photoView(image: Image) -> some View {
Rectangle()
.overlay(alignment: .center) {
image
.resizable()
.scaledToFill()
}
.aspectRatio(4 / 3, contentMode: .fit)
.clipped()
}
}
#Preview {
ScrollWithRemoteImages()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment