SwiftUI 保存图片到相册 
本文描述了在 SwiftUI 应用中如何保存图片到相册
前提条件 
实现步骤 iOS16+ 
声明权限 
在 Info.plist 文件中增加. 注意, 必须提供一个具体的使用例子, 不然可能会被 App Store 审核人员拒绝. Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
xml
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The app needs access to your photo library to save images, such as the Ghibli-style image generated by the app.</string>定义 MediaSaver 
swift
import Photos
struct MediaSaver {
    static func saveImageToPhotoLibrary(url: URL) async throws {
        try await PHPhotoLibrary.shared().performChanges {
            PHAssetCreationRequest.creationRequestForAssetFromImage(atFileURL: url)
        }
    }
    
    static func saveVideoToPhotoLibrary(url: URL) async throws {
        try await PHPhotoLibrary.shared().performChanges {
            PHAssetCreationRequest.creationRequestForAssetFromVideo(atFileURL: url)
        }
    }
}使用 MediaSaver 
swift
Task {
    do {
        try await MediaSaver.saveVideoToPhotoLibrary(url: videoURL)
    } catch {
        print(error.localizedDescription)
    }
}实现步骤 iOS15+ 
声明权限 
在 Info.plist 文件中增加
xml
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The App want save images to the Photo Library</string>定义 ImageSaver 
swift
// ImageSaver.swift
import UIKit
class ImageSaver: NSObject {
    var successHandler: (() -> Void)?
    var errorHandler: ((Error) -> Void)?
    func writeToPhotoAlbum(image: UIImage) {
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveCompleted), nil)
    }
    @objc func saveCompleted(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            errorHandler?(error)
        } else {
            successHandler?()
        }
    }
}使用 ImageSaver 
swift
// ContentView.swift
func savePhoto() {
    guard let processedImage = processedImage else { return }
    let imageSaver = ImageSaver()
    imageSaver.successHandler = {
        print("Success!")
    }
    imageSaver.errorHandler = {
        print("Oops! \($0.localizedDescription)")
    }
    imageSaver.writeToPhotoAlbum(image: processedImage)
}