Mobile Development 12 min read

Optimizing iOS List Page Loading with Prefetch, Preload, and Cache Management

The article explains how to improve slow iOS list pages by using prefetch and preload techniques, caching network responses, handling new‑user scenarios, and implementing a hash‑based cache‑validation system to minimize unnecessary reloads and boost rendering performance.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Optimizing iOS List Page Loading with Prefetch, Preload, and Cache Management

In client‑side development, list‑type pages often rely on network requests, causing slow loading or failures when the network is sluggish. The author describes a strategy for a member product list page that reduces the number of required API calls from ten to three and improves the perceived loading speed.

The core idea is to split page loading into prefetch and preload phases. First, cached data is used to render the page instantly; when the server data arrives, it replaces the local data if it differs, otherwise the cached version remains.

Prefetch – Interface caching

When entering the product page, three interfaces are requested. The network library SVRequest provides built‑in caching. The following code shows how the request is wrapped with a cache block and a reload decision:

self startRequestWithType:SVRequestTypeGet requestURL:requestURL cacheable:YES params:params cacheBlock:^(SVNetworkCache * _Nullable cache, SVRequestControl * _Nonnull requestControl) {
    if (cache.cacheObj && [Reachability currentNetworkType] == NotReachable) {
        [requestControl stop];
    } else {
        [requestControl goOn];
    }
    [self parseData:data successBlock:cacheBlock];
} successBlock:^(id _Nonnull responseObject) {
    NSDictionary *data = [responseObject as:[NSDictionary class]];
    [self parseData:data successBlock:successBlock];
} failureBlock:^(SVRequestError * _Nonnull error, id _Nonnull responseObject) {
    if (failedBlock) { failedBlock(error, responseObject); }
}];

For brand‑new users or users upgrading from an older version, no local cache exists. In this case the app checks the cache status ( check ) and, if empty, proactively requests the data and writes it to the cache so the page never appears empty.

Preload – Layout preparation

To ensure the user sees a fully rendered page after a push , the app performs a preload during initialization. It reads cached data ( cacheData ) and forces layout calculation with layoutIfNeeded . The process keeps FPS stable by avoiding off‑screen rendering and heavy CPU work, delegating drawing to the GPU.

The rendering pipeline on iOS works as follows:

When a VSync signal arrives, the app’s CPU computes view creation and layout.

The result is submitted to the GPU, which performs transformation, composition, and renders to the back buffer.

The video controller displays the bitmap from the back buffer; if CPU/GPU work isn’t finished, the frame is dropped.

UIView triggers layout via layoutSubviews , which marks the layer with setNeedsDisplay . The run‑loop then calls the layer’s display method.

The layer creates a CGContextRef backing store and calls drawRect (or the default Core Graphics API) to draw into the bitmap.

The final bitmap is stored in the layer’s contents property and presented on screen.

Reload – Hash‑based validation

After displaying cached data, the app compares the new network data with the cached version using a hash manager. The SVPCacheManager class stores separate arrays for cache hashes and network hashes and provides methods to configure, append, and compare them:

@objc class SVPCacheManager: NSObject {
    var cacheHash: [String]?
    var netHash: [String]?
    static let shared = SVPCacheManager()
    func config(count: Int) {
        cacheHash = [String](repeating: "", count: count)
        netHash   = [String](repeating: "", count: count)
    }
    func appendCache(index: Int, hash: String) { if hash.count > 0 { cacheHash?[index] = hash } }
    func appendNet(index: Int, hash: String)   { if hash.count > 0 { netHash?[index]   = hash } }
    func isEqual() -> Bool { return cacheHash == netHash }
}

Because many fields (e.g., expire timestamps, H5 HTML, play‑count formats) change frequently, the manager removes such volatile parameters via KVC before computing the MD5 hash. To guarantee deterministic hashes, dictionaries are converted to ordered structures: keys are sorted, values are appended recursively, and the resulting string is hashed.

Analysis

Previously, a metric measured the total time from the first request to the completion of three interfaces. With caching, this metric often reads zero, so the focus shifts to cache‑match rate. Reducing unnecessary reloads improves user experience, which is the ultimate optimization goal.

Reference: iOS 页面渲染 - UIView & CALayer

PerformanceiOSCachingSwifthashprefetchPreload
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.