◉RORK LABJP
●EXPO — EAS Observe now records native crashes (Oct 7). On SDK 57, update to 57.0.21 or later●SDK 58 — SDK 58 Beta has been out since Sep 15. The stable date is still unconfirmed●RN 0.88 — React Native 0.88.x is scheduled for Oct 12, 3 days left●Q&A — People are asking why expo-widgets render blank only in production builds●RORK — GPT-6.1 Sol was added on Sep 29, available on Pro and Max plans●NEW — Building an app for a client? Decide who owns the publishing account first●EXPO — EAS Observe now records native crashes (Oct 7). On SDK 57, update to 57.0.21 or later●SDK 58 — SDK 58 Beta has been out since Sep 15. The stable date is still unconfirmed●RN 0.88 — React Native 0.88.x is scheduled for Oct 12, 3 days left●Q&A — People are asking why expo-widgets render blank only in production builds●RORK — GPT-6.1 Sol was added on Sep 29, available on Pro and Max plans●NEW — Building an app for a client? Decide who owns the publishing account first
Articles/Dev Tools
⬡ Dev Tools/2026-06-24Advanced

Fixing Stutter When a Rork Max SwiftUI Image Grid Scrolls

Measure why a Rork Max SwiftUI image grid stutters while scrolling, then fix it with ImageIO downsampling, off-main-thread decoding, and stable cells to cut real-device hitches.

Rork Max235SwiftUI66Performance25Image ProcessingLazyVGrid

✦ Premium Article

Ask Rork Max to "build a grid screen that shows wallpapers" and you get working SwiftUI in a few minutes. It looks smooth in the simulator. Then you put it on a real device, scroll through a few dozen 4K wallpapers, and the scroll stops keeping up with your finger. As an indie developer running the wallpaper app Beautiful HD Wallpapers, I hit exactly this when I rebuilt its grid with Rork Max.

The cause isn't sloppy generation. The generated code takes the straightforward path of "just display the image," which is correct while the sample images are small. The problem is that the real images your app ships are far larger than what the generator assumed. Let's walk through where to start fixing the naive version so that real-device scrolling comes back — measuring as we go.

Why the freshly generated grid stutters on device

The grid Rork Max hands you first usually looks like this.

struct WallpaperGrid: View {
    let items: [Wallpaper]
    private let columns = [GridItem(.adaptive(minimum: 110), spacing: 2)]
 
    var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 2) {
                ForEach(items) { item in
                    // The common freshly generated shape. It decodes full-resolution images
                    // from the URL and scales them down for display, so when large images
                    // pile up, main-thread decoding overlaps and scrolling stalls.
                    AsyncImage(url: item.fileURL) { image in
                        image.resizable().scaledToFill()
                    } placeholder: {
                        Color(.secondarySystemBackground)
                    }
                    .frame(width: 110, height: 110)
                    .clipped()
                }
            }
        }
    }
}

What makes this heavy? AsyncImage does not "automatically lighten the image to fit the display size." A 3024×4032 wallpaper is decoded into a full-resolution bitmap even when it only needs to fit a 110-point cell. Each image uses tens of megabytes of memory, and when that decode runs on the main thread, frames can't be drawn during it, so scrolling freezes for a moment. Chain that across every visible cell and you have the stutter.

The official docs say AsyncImage is "convenient," but they don't emphasize that it's "not suited to large volumes of high-resolution images." It's a trap you only discover once you feed it genuinely heavy images.

Measure first — numbers, not gut feeling

If you start fixing based on "it feels laggy," you won't know whether your change helped. Build a measurement footing first.

In Xcode Instruments, choose the Animation Hitches template and scroll the grid on a real device. Watch the "hitch time ratio" (milliseconds per second): how many milliseconds of frames were delayed per second of scrolling. Apple's guidance is that it becomes perceptible past 5 ms/s and clearly catches past 10 ms/s.

SymptomWhat the measurement showsLikely cause
Brief freeze at the start of a scrollTime Profiler shows decode functions on the main threadFull-resolution decode
Stutter during fast scrollsHitch time ratio above 10 ms/sPer-cell re-decode and re-render
Gets heavier the further you scrollMemory usage climbs steadilyDecoded bitmaps not being released

I make a habit of taking this measurement "before fixing" and "after each single change." Downsampling alone often drops the hitch substantially, and the numbers tell you when you've done enough. After release, Xcode Organizer's "Hitch Rate" lets you track real users' values, so it doubles as a verification footing.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦If your wallpaper-style image grid stalls on scroll, you can apply a concrete hitch-reducing implementation today
✦You can replace the naive full-resolution image load with memory-friendly ImageIO thumbnail generation
✦You'll be able to use Instruments Hitches to see exactly where and how much your grid stutters, and compare before and after
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $15 for lifetime access
View Membership →

Related Articles

⬡ Dev Tools2026-07-18
The Generated Screen That Quietly Jams at AX5 and in German — Putting Layout Resilience Checks on Rork Max SwiftUI
A record of running every Rork Max generated SwiftUI screen through pseudolocalization and the largest text size to find exactly where it jams. Covers when to reach for ViewThatFits, ScaledMetric and layoutPriority, plus the snapshot checks that catch regressions every time you regenerate.
⬡ Dev Tools2026-05-17
Testing Rork Max SwiftUI Features on a Real Wallpaper App — What Worked, What Needed Fixes
I benchmarked Rork Max's SwiftUI generation against the production code of a wallpaper app I actually run. Here is what shipped as-is, what needed fixing, and what I ended up writing by hand — with working code and on-device measurements.
⬡ Dev Tools2026-05-12
Building a Shared UI Component Library with Swift Package Manager in Rork Max
A practical guide to building a shared SwiftUI component library with Swift Package Manager for indie developers running multiple apps — eliminate duplicate code across wallpaper, healing, and similar app families.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links