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

Swift4+iOS11开发:UIImage无法保存至iPhone相册问题

Hey there! Let's troubleshoot why your image isn't saving to the iPhone photo album. I've spotted a few key issues that are likely causing this problem—let's break them down and fix them step by step:

1. Missing Photo Library Access Permission

First off, iOS requires explicit user permission to save media to the photo album. If you haven't added the required description keys to your Info.plist, the save operation will silently fail (or throw an error, depending on the iOS version).

Add these two keys to your Info.plist (including both ensures compatibility across older and newer iOS versions):

  • NSPhotoLibraryAddUsageDescription: A clear explanation of why you need access (e.g., "We need permission to save your captured images to your photo album.")
  • NSPhotoLibraryUsageDescription: Older iOS versions rely on this key, so it's safe to include it as well.

To add these, right-click your Info.plist → select "Open As" → "Source Code", then paste these lines inside the <dict> tag:

<key>NSPhotoLibraryUsageDescription</key>
<string>We need permission to save your captured images to your photo album.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need permission to save your captured images to your photo album.</string>

2. CIImage-Based UIImage Has No Backing CGImage

Your current code creates a UIImage directly from a CIImage using UIImage(ciImage: ciImage...). The problem here is that this type of UIImage doesn't have a concrete CGImage backing it up—and UIImageWriteToSavedPhotosAlbum requires a valid pixel representation to save successfully.

Let's fix your CMSampleBuffer extension to render the CIImage into a proper CGImage first:

extension CMSampleBuffer {
    func image(orientation: UIImageOrientation = .up, scale: CGFloat = 1.0) -> UIImage? {
        guard let buffer = CMSampleBufferGetImageBuffer(self) else { return nil }
        let ciImage = CIImage(cvPixelBuffer: buffer)
        
        // Render CIImage to CGImage to ensure a valid pixel representation
        let context = CIContext(options: [.useSoftwareRenderer: false])
        guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return nil }
        
        return UIImage(cgImage: cgImage, scale: scale, orientation: orientation)
    }
}

3. Add Safety Checks & Ensure Main Thread Execution

It's smart to add safeguards for nil images and explicitly run the save operation on the main thread (since photo library interactions and UI alerts should always happen on the main thread).

Update your saveButton action in PreviewViewController:

@IBAction func saveButton(_ sender: Any) {
    guard let imageToSave = imageView.image else {
        let ac = UIAlertController(title: "Oops!", message: "No image available to save.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
        return
    }
    
    // Dispatch to main thread for safe photo library access
    DispatchQueue.main.async {
        UIImageWriteToSavedPhotosAlbum(imageToSave, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
}

Bonus: Add a Check for Nil Image in ViewController

To avoid passing a nil image to PreviewViewController, add a safety check in your prepare(for:sender:) method:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showPhotoSegue" {
        guard let capturedImage = videoCapture.image else {
            let ac = UIAlertController(title: "Error", message: "No image was captured.", preferredStyle: .alert)
            ac.addAction(UIAlertAction(title: "OK", style: .default))
            present(ac, animated: true)
            return
        }
        let previewVC = segue.destination as! PreviewViewController
        previewVC.image = capturedImage
    }
}

After making these changes, your image should save to the photo album without issues. If you run into any other snags, feel free to follow up!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:19:14