Jamie Forrest
Jamie Forrest

Reputation: 11113

Using Swift functions in Objective-C that have protocol-typed parameters

I have a Swift class called Helpers defined as follows:

class Helpers : NSObject {
    class func sayValue(value:Printable) {
        println(value)
    }
}

I am trying to use this in an Objective-C .m file, like so:

[Helpers sayValue:@"Hello"];

But the compiler is complaining with the error: No known class method for selector 'sayValue:'

However if I change the sayValue to have a strict type, it works fine:

class Helpers : NSObject {
    class func sayValue(value:String) {
        println(value)
    }
}

What's going on here?

Upvotes: 0

Views: 861

Answers (1)

matt
matt

Reputation: 535315

You've already figured it out. Swift protocols don't map as types into Objective-C.

Always just ask yourself "Could I say this in Objective-C?" You can't say this in Objective-C:

+ (void) sayValue: (Printable*) value { ... }

That's illegal, because Printable (a protocol) isn't a type. So your Swift function defined that way doesn't magically map upward into Objective-C, as it has nothing to map to. It is filtered out, and Objective-C never sees it.

What I'm finding is that all this works remarkably cleanly. I was afraid that a Swift class that uses any non-Objective-C features wouldn't map to an Objective-C class at all. But, on the contrary, you can use all the pure-Swift features you like, and they simply don't map up into Objective-C: they are cleanly filtered out, and those parts of your Swift class that do map into Objective-C work just fine from Objective-C. It's quite brilliant.


You are free to define a protocol that maps as a type for purposes of, say, defining a delegate. But to do that, you must expose the protocol using @objc. For example, from one of my apps:

@objc protocol ColorPickerDelegate {
    func colorPicker (/*...*/)
}

class ColorPickerController : UIViewController {
    weak var delegate: ColorPickerDelegate?
    // ...
}

You can't talk that way unless the protocol is @objc. Now Objective-C understands the type of delegate to mean id<ColorPickerDelegate> and you're in business.

(So you could probably talk the way you're suggesting by defining an @objc protocol MyPrintable which does nothing but adopt Printable; I haven't tried it, however, so that's just a conjecture.)

Upvotes: 4

Related Questions