iOS Swift 5中从相机/相册选图:预判断大小及最优方案
iOS相册多选/相机拍照上传:预加载判断图片大小与最优实现方案
一、能不能在加载进应用前判断图片大小?
完全可以:
- 相册选图:借助
Photos框架的PHAsset,可以直接获取原图的文件大小,无需将图片解码为UIImage加载到内存中。 - 相机拍照:拍照完成后,系统会返回图片的本地文件路径,直接读取该路径的文件大小即可,同样不需要先加载图片。
二、最优实现方案
1. 相册选图:通过PHAsset获取单图大小
首先导入Photos框架,在用户选完图片后,通过PHAsset异步获取图片大小(不占用额外内存):
import Photos // 异步获取PHAsset对应的文件大小 func getAssetFileSize(_ asset: PHAsset, completion: @escaping (Int64?) -> Void) { let options = PHImageRequestOptions() options.isSynchronous = false options.deliveryMode = .highQualityFormat PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { _, _, _, info in let fileSize = info?[PHImageFileSizeKey] as? Int64 completion(fileSize) } }
如果使用iOS14+推荐的PHPickerViewController,可以从PHPickerResult中提取PHAsset:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) let assets = results.compactMap { $0.assetIdentifier }.compactMap { PHAsset.fetchAssets(withLocalIdentifiers: [$0], options: nil).firstObject } // 批量获取大小 var totalSize: Int64 = 0 let group = DispatchGroup() for asset in assets { group.enter() getAssetFileSize(asset) { size in if let size = size { totalSize += size } group.leave() } } group.notify(queue: .main) { // 校验总大小 self.checkTotalSize(totalSize) } }
2. 相机拍照:读取本地文件大小
相机拍照完成后,从UIImagePickerController的info字典中获取图片本地URL,直接读取文件大小:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) guard let imageURL = info[.imageURL] as? URL else { return } do { let fileAttributes = try FileManager.default.attributesOfItem(atPath: imageURL.path) guard let fileSize = fileAttributes[.size] as? Int64 else { return } // 校验是否可以加入已选列表 if checkCanAddImage(size: fileSize) { // 处理后续逻辑,比如保存URL或asset } } catch { print("读取图片大小失败:\(error)") } }
3. 总大小校验逻辑
维护一个变量记录已选图片总大小,每次新增前判断是否超出5MB限制:
private var totalSelectedSize: Int64 = 0 private let maxTotalSize: Int64 = 5 * 1024 * 1024 // 5MB private func checkCanAddImage(size: Int64) -> Bool { guard totalSelectedSize + size <= maxTotalSize else { let alert = UIAlertController(title: "提示", message: "已选图片总大小超过5MB限制,请减少图片或选择更小的文件", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return false } totalSelectedSize += size return true } // 重置总大小(比如用户取消选择时) private func resetTotalSize() { totalSelectedSize = 0 }
4. 额外优化建议
- 优先用PHPicker:iOS14+推荐使用
PHPickerViewController,它不需要请求相册全权限,仅请求选中图片的权限,用户体验更好,多选支持更完善。 - 批量处理提升效率:如果是多选场景,用
DispatchGroup批量获取所有图片大小,避免逐个处理的等待时间。 - 提供压缩备选方案:如果用户选中的单图或总大小超出限制,除了提示,还可以提供图片压缩功能(比如调整分辨率、降低JPEG质量),提升用户体验:
// 简单的图片压缩方法 func compressImage(_ image: UIImage, targetSizeMB: CGFloat) -> Data? { var compressionQuality: CGFloat = 1.0 var imageData = image.jpegData(compressionQuality: compressionQuality) while let data = imageData, Double(data.count) / (1024*1024) > targetSizeMB, compressionQuality > 0.1 { compressionQuality -= 0.1 imageData = image.jpegData(compressionQuality: compressionQuality) } return imageData } - 内存优化:不要在不必要的时候保留
UIImage实例,处理完上传逻辑后及时释放,避免内存飙升。
内容的提问来源于stack exchange,提问作者Prabhu
相关产品推荐
相关产品推荐

