You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中如何快速获取手机全部图片并优化加载性能?

How to Speed Up Loading 1000+ Photos for Multi-Select Album

Hey there! I see exactly why your current code is dragging with 1000+ images—you’re loading every single photo synchronously upfront, which clogs up the main thread and wastes memory. Let’s fix this with practical, step-by-step optimizations:

The Core Issues in Your Current Code

  • Synchronous Requests: Setting requestOptions.isSynchronous = true forces each image request to block until it finishes. With 1000 photos, this means your app freezes while processing one image at a time.
  • Preloading All Images: Storing every UIImage in an array immediately eats up tons of memory and delays any user interaction until all images are loaded.

Step-by-Speed Optimizations

1. Switch to Asynchronous Image Loading

First, ditch synchronous requests. Async loading lets the system handle multiple image requests in parallel without blocking the main thread. Update your request options for speed:

let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = false // Critical change
requestOptions.resizeMode = .fast // Prioritize speed over pixel-perfect resizing
requestOptions.deliveryMode = .fastFormat // Get a quick preview first (optional: load high-res later)
requestOptions.isNetworkAccessAllowed = true // Include iCloud photos if needed

2. Load Images On-Demand (Not All At Once)

Instead of preloading every image into an array, store the PHAsset objects first, then load images only when they’re visible in your collection view. This cuts initial load time drastically.

First, fetch and store the assets:

func getAllPhotoAssets() -> [PHAsset] {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]
    let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
    
    var assets = [PHAsset]()
    fetchResult.enumerateObjects { asset, _, _ in
        assets.append(asset)
    }
    return assets
}

Then, load images only when cells appear in your collection view:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
    let asset = yourAssetArray[indexPath.item]
    
    // Cancel any stale request for this cell to avoid wrong images
    PHImageManager.default().cancelImageRequest(cell.imageRequestID)
    
    // Request the image asynchronously
    cell.imageRequestID = PHImageManager.default().requestImage(
        for: asset,
        targetSize: CGSize(width: 200, height: 200),
        contentMode: .aspectFill,
        options: requestOptions
    ) { [weak cell] image, info in
        guard let cell = cell else { return }
        cell.photoImageView.image = image
    }
    
    // Set selection state (track selected assets in a separate array)
    cell.isSelected = yourSelectedAssets.contains(asset)
    return cell
}

3. Add Request Cancellation

Make sure your custom cell can cancel old requests when reused, so you don’t waste resources on images that are no longer visible:

class PhotoCell: UICollectionViewCell {
    @IBOutlet weak var photoImageView: UIImageView!
    var imageRequestID: PHImageRequestID? = nil
    
    override func prepareForReuse() {
        super.prepareForReuse()
        photoImageView.image = nil // Clear old image
        if let requestID = imageRequestID {
            PHImageManager.default().cancelImageRequest(requestID)
        }
    }
}

4. Optional: Boost Performance with Image Caching

Use PHCachingImageManager instead of the default manager to automatically cache loaded images. Scrolling back to previously seen cells will be instant:

let cachingImageManager = PHCachingImageManager()

// Enable caching in viewDidLoad
override func viewDidLoad() {
    super.viewDidLoad()
    cachingImageManager.startCachingImages(
        for: yourAssetArray,
        targetSize: CGSize(width: 200, height: 200),
        contentMode: .aspectFill,
        options: requestOptions
    )
}

// Stop caching when the view disappears to free memory
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    cachingImageManager.stopCachingImages(
        for: yourAssetArray,
        targetSize: CGSize(width: 200, height: 200),
        contentMode: .aspectFill,
        options: requestOptions
    )
}

Why This Works

  • Async loading lets the system handle multiple requests in parallel, so your app stays responsive.
  • On-demand loading means you only load images the user can see right away, cutting initial load time from seconds to milliseconds.
  • Cancellation and caching eliminate wasted work and make scrolling smooth even with thousands of photos.

内容的提问来源于stack exchange,提问作者Gaurav Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:40:50