Can Swift Method Defined on Extensions on Protocols Accessed in Objective-c

Anthony Mattox picture Anthony Mattox · Sep 24, 2015 · Viewed 10.5k times · Source

Is it possible to call methods defined in a protocol extension in Swift from Objective-C?

For example:

protocol Product {
    var price:Int { get }
    var priceString:String { get }
}

extension Product {
    var priceString:String {
        get {
            return "$\(price)"
        }
    }
}

class IceCream : Product {
    var price:Int {
        get {
            return 2
        }
    }
}

The price string of an instance of IceCream is '$2' and can be accessed in Swift, however the method is not visible in Objective-C. The compiler throws the error 'No visible @interface for 'IceCream' declares the selector ...'.

In my configuration, if the method is defined directly in the Swift object's implementation, everything works as expected. i.e.:

protocol Product {
    var price:Int { get }
    var priceString:String { get }
}

class IceCream : Product {
    var price:Int {
        get {
            return 2
        }
    }
    var priceString:String {
        get {
            return "$\(price)"
        }
    }
}

Answer

Steve Madsen picture Steve Madsen · Jan 27, 2016

I am nearly certain the answer to this is "no", although I haven't found official Apple documentation that spells it out.

Here is a message from the swift-evolution mailing list discussing the proposal to use dynamic dispatch for all method calls, which would provide calling semantics more like Objective-C:

Again, the sole exception to this is protocol extensions. Unlike any other construct in the language, protocol extension methods are dispatched statically in a situation where a virtual dispatch would cause different results. No compiler error prevents this mismatch. (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001707.html)

Protocol extensions are a Swift-only language feature, and as such are not visible to objc_msgSend().