【问题标题】:Extension method doesn't work: Value of type 'UIImage' has no member 'compress'扩展方法不起作用:“UIImage”类型的值没有成员“压缩”
【发布时间】:2019-05-10 18:15:28
【问题描述】:

我创建了一个新文件 UIImage+compress.swift,它与我的 PhotoController.swift 位于同一目录中。我一直在寻找在存储图像之前压缩图像的方法,并找到了解释该过程的以下链接:How to compress of reduce the size of an image before uploading to Parse as PFFile? (Swift)

我尝试直接为图像调用 UIImageJPEGRepresentation ,但这并没有让我到任何地方。尝试公开扩展方法,希望能解决问题,但也没有成功。我试图在 stackOverflow 中寻找类似的问题,但它们的不同之处在于没有人解释为什么该方法不可用。

这是扩展方法的代码:

import UIKit

extension UIImage {
enum JPEGQuality: CGFloat {
    case lowest  = 0
    case low     = 0.25
    case medium  = 0.5
    case high    = 0.75
    case highest = 1
}

/// Returns the data for the specified image in JPEG format.
/// If the image object’s underlying image data has been purged, calling this function forces that data to be reloaded into memory.
/// - returns: A data object containing the JPEG data, or nil if there was a problem generating the data. This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format.
func jpeg(_ jpegQuality: JPEGQuality) -> Data? {
    return UIImageJPEGRepresentation(self, jpegQuality.rawValue)
}

}

这是我尝试调用扩展方法的 PhotoController 的代码:

class PhotoController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

... ...

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    let mediaType = info[UIImagePickerControllerMediaType] as! NSString



    if mediaType.isEqual(to: kUTTypeImage as String) {
        let image = info[UIImagePickerControllerOriginalImage] as! UIImage

        var res = image.jpeg(.lowest) as! UIImage

        if (newMedia == true) {
            UIImageWriteToSavedPhotosAlbum(res,
                                           self,
                                           #selector(PhotoController.image(image:didFinishSavingWithError:contextInfo:)),
                                           nil)
            }
        }
        self.dismiss(animated: true, completion: nil)
    }

}

我不断收到错误消息:“UIImage”类型的值没有“压缩”成员。

另外,如何打印图像大小以确保它确实被压缩了?

【问题讨论】:

  • 该代码无法在 Swift 4/5 中编译。你确定为文件 UIImage+compress.swift 选择了“Target Membership”吗?
  • @MartinR 你是什么意思?
  • 鉴于didFinishPickingMediaWithInfo 的签名,您似乎也在使用旧版本的 Swift。

标签: ios swift


【解决方案1】:

以下是如何使您的 Swift 文件成为目标的一部分,以便其他代码可以看到它。

首先,单击项目,编辑该应用程序目标,然后找到构建阶段。打开编译源部分。

点击左下角的加号按钮。找到您的文件并选择它。 (如果您没有看到它列出,请选择添加其他并找到它。)

【讨论】:

    【解决方案2】:

    可能是编译器故障,但不要将响应分配给同一对象UIImage,因为它的类型为Data

     let res = image.compress(.lowest)
    

    【讨论】:

    • 还是同样的错误:'UIImage' 类型的值没有成员'compress'
    • 此扩展未正确链接
    • 如何正确链接
    • 点击swift文件并勾选target membership
    • 我的文件选项中没有看到目标成员身份
    【解决方案3】:

    您的扩展中声明的“压缩”方法在哪里?根据您的设置,您需要这样做...

    image.jpeg(.medium)
    

    【讨论】:

      【解决方案4】:

      该方法被称为jpeg(_:),而不是compress

      let imageData = image.jpeg(.lowest)
      

      由于返回值是可选的,您可能需要检查:

      guard let imageData = image.jpeg(.lowest) else { return }
      

      要获取字节大小,只需查看imageData.count

      【讨论】:

      • 我一路重命名,忘记更新了。感谢您指出!
      • @ShivanshSuhane 在这种情况下,您可能还想更新错误消息。
      【解决方案5】:

      我仍然不知道为什么扩展方法在单独的文件中不起作用。我尝试了@RajeshKumar R 的建议,并且扩展程序仍在 PhotoController.swift 文件中时有效。

      使用最低设置的.jpeg功能后,图像大小从14 MB缩小到14 MB。

       Image size: 13671.8408203125
       Compressed image size: 7796.853515625 
      

      以下是如何使代码正常工作。

      func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
      
          let mediaType = info[UIImagePickerControllerMediaType] as! NSString
      
      
      
          if mediaType.isEqual(to: kUTTypeImage as String) {
              let image = info[UIImagePickerControllerOriginalImage] as! UIImage
              printImageSize(image: image)
      
              var imageData = image.jpeg(.lowest)
      
              let imageCompressed = UIImage(data: imageData!)
              printImageSize(image: imageCompressed!)
      
              if (newMedia == true) {
                  UIImageWriteToSavedPhotosAlbum(imageCompressed!,
                                                 self,
                                                 #selector(PhotoController.image(image:didFinishSavingWithError:contextInfo:)),
                                                 nil)
              }
          }
          self.dismiss(animated: true, completion: nil)
      }
      

      【讨论】:

      • “我仍然不知道为什么扩展方法在单独的文件中不起作用”。你被告知该怎么做:确保 UIImage+compress.swift 是应用程序目标的一部分。看来你没有这样做。
      • @matt “我的文件选项中没有看到目标成员资格 – Shivansh Suhane 1 小时前” 不知道为什么。我仍在努力解决这个问题
      • 您可能看不到它,但这仍然是您原来问题的正确答案。
      • 好的,我用万无一失的说明给出了答案。
      猜你喜欢
      • 2016-03-11
      • 2021-06-17
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多