从 Objective-C 文件调用 Swift UIImageView 扩展中的方法

Call Method in Swift Extension of UIImageView from Objective-C File

我可以从 Objective-C 文件调用 Swift 文件中的 UIImage 扩展。

但由于某些原因,我无法在 UIImageView 的扩展上调用以下方法。 UIImageView 是否有问题,是我的语法不对还是哪里出了问题?

extension UIImageView {
    /// Retrieve the scaled size of the image within this ImageView.
    /// - Returns: A CGRect representing the size of the image after scaling or nil if no image is set.
    func getScaledImageSize() -> CGRect? {
        if let image = self.image {
            return AVMakeRect(aspectRatio: image.size, insideRect: self.frame);
        }

        return nil;
    }
}

Objective-C 文件中的代码:

 CGRect myRect = [self.imageView getScaledImageSize];

给出 'no visible interface for UIImageView declares the selector getScaledImageSize' 错误

扩展不可见,因为 Swift 选项在 Objective-C 中并不存在。另外,因为 CGRect 是结构类型而不是对象类型,所以它不能在 Objective-C.

中表示为 nil

将您的方法更改为类似这样的方法可能是解决您的问题的一种方法:

extension UIImageView {

    @objc
    func getScaledImageSize() -> CGRect {

        // ...

        return .zero;
    }
}

请注意,您需要使用 @objc 注释该方法才能将其正确公开给 Objective-C。

来自Swift 4.2 Language Guide

The concept of optionals doesn’t exist in C or Objective-C. The nearest thing in Objective-C is the ability to return nil from a method that would otherwise return an object, with nil meaning “the absence of a valid object.” However, this only works for objects—it doesn’t work for structures, basic C types, or enumeration values. For these types, Objective-C methods typically return a special value (such as NSNotFound) to indicate the absence of a value. This approach assumes that the method’s caller knows there’s a special value to test against and remembers to check for it. Swift’s optionals let you indicate the absence of a value for any type at all, without the need for special constants.

您至少需要解决三件事。

在您的 Objective-C 文件中,您需要添加以下 import 语句:

#import "ProductModuleName-Swift.h"

其中 "ProductModuleName" 是您的项目名称。

您需要将 @objc 属性添加到您的扩展 class:

@objc extension UIImageView

您需要将方法更改为 return 非可选值。这是一个建议的实现:

func getScaledImageSize() -> CGRect {
    if let image = self.image {
        return AVMakeRect(aspectRatio: image.size, insideRect: self.frame)
    }

    return CGRect.zero
}