Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObjC protocol Implementation in Swift

Ok here is the big problem. I had a library written in ObjC(this). There we had a defined protocol. When I tried to use it in swift file I get constantly:

Type "XXX" does not conform to protocol "XXX"

To simplify things I made up a test project - it should be created as Swift project.

Then create ObjC header file(I called it StupidProtocol.h) with following protocol inside(please note each name and value to exactly match the given including uppercase/lowercase):

@protocol MyProtocol <NSObject>

- (NSString *)getAxisLabel:(id)axis Value:(CGFloat)value;

@end

In bridging header:

#import "StupidProtocol.h"

And then back in Swift file:

class ViewController: UIViewController, MyProtocol
{
    func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! {
        return ""
    }
}

And baam we got this error again even though auto-complete finishes the getAxisLabel function for me.

I strongly suspect that the problem is with argument "value" and it's function parameter "Value".

Any help will be highly appreciated.

EDIT

Please note that this library is not technically mine, so I cannot change it. I need a way to use it in Swift without changing it's original declaration. My example is only to simplify my problem.

WHAT I TRIED

I have tried following scenarios with no success:

'has different arguments name from those required by protocol' error

func getAxisLabel(axis: AnyObject!, Value value: CGFloat) -> String! {
    return ""
}

'has different arguments name from those required by protocol' error

func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> String! {
    return ""
}

'type does not conform to protocol'

func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> NSString! {
    return ""
}

SOLUTION

See accepted answer

like image 252
hris.to Avatar asked Jun 29 '15 07:06

hris.to


People also ask

What is a protocol OBJC?

Advertisements. Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation. Protocols are implemented in the classes conforming to the protocol.

Can Objective-C implement Swift protocol?

In order to use Swift code inside Objective-C one must scrifice some Swift features and write a wrapper around original Swift code that won't use non-compatible features (like structs, generics, enum associated values, protocol extensions etc.). All wrapper classes must inherit NSObject .

Why do we use @objc in Swift?

There are two keywords to keep in mind when dealing with interoperability: @objc means you want your Swift code (class, method, property, etc.) to be visible from Objective-C. dynamic means you want to use Objective-C dynamic dispatch.

What is difference between Objective-C protocol and Swift protocol?

In Objective-C, protocols are declared with the “@protocol” keyword. Below is an example of declaring a protocol containing one required method. In Swift, the syntax is a little different but the idea is the same. In Objective-C, you add the protocol name in angle brackets beside the class interface declaration.


1 Answers

I don't know if this is a bug or not. The Objective-C protocol method

- (NSString *)getAxisLabel:(id)axis Value:(CGFloat)value;

(with uppercase "V" in Value:) is mapped to Swift as

func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String!

(with lowercase "v" in value:), but none of

func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! { }
func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> String! { }

is accepted by the compiler to satisfy the protocol requirement.

As a workaround, you can annotate the method with an explicit Objective-C selector name:

class ViewController: UIViewController, MyProtocol
{
    @objc(getAxisLabel:Value:)
    func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! {
        return ""
    }
}
like image 73
Martin R Avatar answered Oct 01 '22 08:10

Martin R