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

PHImageManager请求精确尺寸图片在部分iOS设备不生效怎么办

问题原因
  • 苹果在部分iOS版本(包含iOS14.4、iOS15正式版等)中对PHImageManager的resizeMode = .exact逻辑实现存在兼容差异:当搭配contentMode = .aspectFill使用时,系统仅会将原始图片等比缩放至宽/高中某一维度匹配目标尺寸,不会自动裁剪超出目标尺寸的另一维度内容,因此3:4比例的原始图片缩放到宽度266时,高度自动保留为354,和你的日志输出一致。
  • 额外隐含坑点:PHImageManager传入的targetSize单位为*点(Point)*而非像素,若未结合当前屏幕的scale参数换算,最终返回的图片像素尺寸也会和预期的266x266像素存在偏差。
解决方案

方案1:手动裁剪(兼容性最高,全版本适用)

拿到系统返回的图片后,自行裁剪到目标尺寸,不受系统API实现差异影响,参考代码如下:

// 扩展UIImage添加裁剪方法
extension UIImage {
    func cropped(to targetSize: CGSize) -> UIImage? {
        let scale = UIScreen.main.scale
        let realPixelSize = CGSize(width: targetSize.width * scale, height: targetSize.height * scale)
        
        let widthRatio = realPixelSize.width / size.width
        let heightRatio = realPixelSize.height / size.height
        let scaleFactor = max(widthRatio, heightRatio)
        
        let scaledSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)
        let origin = CGPoint(x: (realPixelSize.width - scaledSize.width) / 2, y: (realPixelSize.height - scaledSize.height) / 2)
        
        UIGraphicsBeginImageContextWithOptions(realPixelSize, false, scale)
        draw(in: CGRect(origin: origin, size: scaledSize))
        let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return croppedImage
    }
}

// 在原有请求的回调里调用裁剪方法
let requestId = manager.requestImage(for: asset, targetSize: imageSize, contentMode: .aspectFill, options: fullsizeOptions, resultHandler: { (image, info) -> Void in
   guard let rawImage = image else {
      print("🌈 detailed image fetch (\(asset.localIdentifier)) failed")
      return
   }
   // 手动裁剪到266x266
   let targetImage = rawImage.cropped(to: CGSize(width: 266, height: 266))
   print ("real image size: \(targetImage?.size)")
})

方案2:调整请求参数适配系统逻辑

如果不想手动裁剪,可以修改请求参数保证系统返回尺寸正确:

  1. 如果你需要的266是像素单位,先把targetSize转换为点单位:
let scale = UIScreen.main.scale
let imageSize = CGSize(width: 266 / scale, height: 266 / scale)
  1. 新增normalizedCropRect参数指定裁剪区域,强制系统按比例裁剪:
fullsizeOptions.normalizedCropRect = CGRect(x: 0, y: 0, width: 1, height: 1)

注意该参数仅在resizeMode = .exact时生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:54:00