WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

Should I always downsample when loading user-saved images?

Forums > SwiftUI

My app allows users to select and save images from the Photos app.

The saved image is stored in the core data as a Binary Data type, and when I show the image, I use a GeometryReader to downsample the image to a certain size and show the image. However, I feel that the performance of the app is not good and I want to improve it, but I don't know how to improve it.

I would be grateful if you could give me some advice to improve it.

struct ContextView: View {
    @State private var seletedItem: Item?
    var body: some View {
        MainListView()
            .sheet(item: $seletedItem) { item in
                GeometryProxy { proxy in
                    let size = proxy.size
                    DetailImageView(item: item, size: size)
                        .ignoresSafeArea(.container, edges: .top)

                }
            }
    }
}

struct DetailImageView: View {
    var item: Item
    var size: CGSize
    private var imageHeight: CGFloat {
        size.height * 0.56
    }
    @State private var uiImage: UIImage? = nil

    var body: some View {
        ScrollView {
            GeometryReader { proxy in
                let childSize = proxy.size
                if let uiImage {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFill()
                        .frame(width: childSize.width, height: childSize.height)
                }
            }
            .frame(height: size.height)
        }
        .coordinateSpace(name: "scroll")

        .task(id: size) {
            uiImage = downsampleImage(imageData: item.imageData,
                                      to: CGSize(width: size.width, height: imageHeight))
        }
        .onChange(of: item.unwrappedImageData) { newImageData in
            updateImage(data: newImageData, width: size.width, height: imageHeight)
        }
        .onDisappear {
            uiImage = nil
        }
    }

    private func downsampleImage(imageData: Data, to pointSize: CGSize, scale: CGFloat = UIScreen.main.scale) -> UIImage {
        let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
        guard let imageSource = CGImageSourceCreateWithData(imageData as CFData, imageSourceOptions) else { return UIImage() }

        let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
        let downsampleOptions = [
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceShouldCacheImmediately: true,
            kCGImageSourceCreateThumbnailWithTransform: true,
            kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels
        ] as CFDictionary

        guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else { return UIImage() }
        return UIImage(cgImage: downsampledImage)
    }
}

2      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.