0

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?

1 Answer 1

4

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.)

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks @Matt. What about a function that takes an Any type parameter? I would think that would map to id in Objective-C, but I get the same error as the one above. Is there a way to write a function in Swift that takes an Any type, and can still be used in Objective-C?
It would probably map to Obj-C if the protocol were a @class_protocol.
I answered my own question. Got it working using AnyObject in the Swift function to magically get bridged to id in objc.
@JamieForrest Right, AnyObject and id are bridged to one another. Basically that is what AnyObject is; in fact, as far as I can tell it only works properly in the presence of Objective-C. See my question here along with the answer and commentary thereon: stackoverflow.com/questions/24154304/…
You can also have your Swift protocol extend (?) NSObject rather than re-casting or re-extending in ObjC

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.