user1904273
user1904273

Reputation: 4764

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

I am able call extensions of UIImage in a Swift file from an Objective-C file.

But for some reason, I cannot call the following method on an extension of UIImageView. Is there some issue with UIImageView, is my syntax off or what could be wrong?

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;
    }
}

Code in Objective-C file:

 CGRect myRect = [self.imageView getScaledImageSize];

Gives 'no visible interface for UIImageView declares the selector getScaledImageSize' error

Upvotes: 1

Views: 1327

Answers (2)

Mike Taverne
Mike Taverne

Reputation: 9362

There are at least three things you need to fix.

In your Objective-C file, you need to add the following import statement:

#import "ProductModuleName-Swift.h"

where "ProductModuleName" is the name of your project.

You need to add the @objc attribute to your extension class:

@objc extension UIImageView

You need to change the method to return a non-optional value. Here is a suggested implementation:

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

    return CGRect.zero
}

Upvotes: 2

ryanecrist
ryanecrist

Reputation: 338

The extension isn't visible because Swift optionals don't really exist in Objective-C. Also, because CGRect is a structure type and not an object type, it can't be represented as nil in Objective-C.

Changing your method to something like this would be one potential solution to your problem:

extension UIImageView {

    @objc
    func getScaledImageSize() -> CGRect {

        // ...

        return .zero;
    }
}

Note that you need to annotate the method with @objc to properly expose it to Objective-C.

From the 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.

Upvotes: 1

Related Questions