Importing a Swift protocol in Objective-C class

Objective CSwift

Objective C Problem Overview


I try to import a Swift Protocol named AnalyticProtocol into an Objective-C class named AnalyticFactory.

protocol AnalyticProtocol
{

}

I'm starting from an existing Objective-C project (I didn't create a new Swift project with xCode and I didn't found how configure my Objective-C project to be a Swift project in xCode 6).

In my Swift file I included the .h file named MyProjectName-Swift.h but the compiler return me an error telling me that it doesn't exist. So, I created a .h file named MyProjectName-Swift.h which is actually empty (I don't know what I should put inside).

In the Apple documentation they said that I have to include my .h file named MyProjectName-Swift.h in my .m file. But I need to include it not into my .mfile but into my .h. Does this can be problematic?

When I try to compile I've got this error: :0: error: xxxAnalyticFactory.h:39: cannot find protocol declaration for 'AnalyticProtocol'

And the incriminated code:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

I think I don't understand well how can I import a Swift protocol into an Objective-C class.

Does anyone see an error in what I'm doing?

Objective C Solutions


Solution 1 - Objective C

You need to add the @objc attribute to your Swift protocol like so:

@objc protocol AnalyticProtocol {

}

Solution 2 - Objective C

It is not possible to import the Xcode generated Swift header in objC header files.

So, since you want to use Swift code in an objC header file, you will need to "forward declare" the classes and protocols you want to use in the objC header file, like this:

@protocol AnalyticProtocol;

You can now use the protocol in your objC class declaration:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

In your implementation file (the objC .m file), you can import the Xcode generated Swift header ("ProductModuleName-Swift.h") file and the correct implementation AnalyticProtocol will now be known to the compiler.

This is also described in official Importing Swift into Objective-C

Note that XCode will give a warning in the objC header file when you use the forward declared protocol ("Cannot find protocol definition for 'AnalyticProtocol'), but this is can be ignored - the implementation will be found at compile time.

Solution 3 - Objective C

For anybody who simply needs to adopt a protocol – you can do this in two steps, without generating any warnings or errors:

  1. In your .swift file, add @objc before the protocol name:

     @objc protocol AnalyticProtocol {
    
     }
    
  2. In your .m file, import the generated Swift header and adopt the protocol in a private category. (The header file is named automagically):

     #import "ProductModuleName-Swift.h"
     
     @interface AnalyticFactory () <AnalyticProtocol>
     
     @end
    

This is Apple’s recommended approach. You can learn more about mixing and matching Objective-C and Swift here: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

Solution 4 - Objective C

We can use swift protocols in Objective C with few changes to the code. Also, @objc declared protocols let you have optional and required methods without default implementations. It comes with pros and cons.

We could actually re-name the protocol name to a more descriptive when using in Objective C. I make use of "@objc(alias_name)".

Here is the code, Let's have a swift protocol with @objc attribute and alias name to use in the ObjC code.

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

Now lets farword declare our protocol in .h file

@protocol ObjTableViewReloadable;

You can now conform to this protocol in .m file and add required methods implementation.

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

Solution 5 - Objective C

If your are creating a framework, the required import

#import "ProductModuleName-Swift.h"

changes to:

#import <ProductModuleName/ProductModuleName-Swift.h>

In this case you also must make the swift protocol public:

@objc public protocol AnalyticProtocol {
  func something();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJean LebrumentView Question on Stackoverflow
Solution 1 - Objective CJamie ForrestView Answer on Stackoverflow
Solution 2 - Objective CPelle Stenild ColtauView Answer on Stackoverflow
Solution 3 - Objective CChris NoletView Answer on Stackoverflow
Solution 4 - Objective CVinay HosamaneView Answer on Stackoverflow
Solution 5 - Objective CMichalView Answer on Stackoverflow