Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent circular reference when Swift bridging header imports a file that imports Hopscotch-Swift.h itself

I am integrating Swift into a large existing Objective C project and have run into what I think is a circular reference.

The classes in question are as follows:

Objective C Controller

#import "Hopscotch-Swift.h"  @interface MyController : UIViewController<MyProtocol>    ... @end 

Swift Protocol

@objc protocol MyProtocol: NSObjectProtocol {    ... } 

Bridging Header

#import "MyController.h" 

This code fails to compile because the Hopscotch-Swift.h file will not generate.

I think this is due to a circular reference error as I can import Hopscotch-Swift.h into objective c headers that are not included in Hopscotch-Bridging-Header.h and it works fine.

Is there a workaround for this issue or should I file a radar with Apple?

like image 221
Samantha John Avatar asked Sep 04 '14 16:09

Samantha John


People also ask

How do you use bridging headers in Swift?

Alternatively, you can create a bridging header yourself by choosing File > New > File > [operating system] > Source > Header File. Edit the bridging header to expose your Objective-C code to your Swift code: In your Objective-C bridging header, import every Objective-C header you want to expose to Swift.

How do I manually create a bridging header in Swift?

To create an Objective-C bridging header file, all you need to do is drag some Objective-C code into your Swift project – Xcode should prompt you with the message "Would you like to configure an Objective-C bridging header?" Click "Creating Bridging Header" and you'll see a file called YourProjectName-Bridging-Header.

What is Bridge header in Swift?

Its correct to say, Bridging header allows user to use Objective-C classes/files in their swift code in same project. A Swift bridging header allows you to communicate with your old Objective-C classes from your Swift classes. You will need one if you plan to keep portions of your codebase in Objective-C.


2 Answers

Forward declaration should work, in your case.

In your .h:

@protocol MyProtocol;  @interface MyController : UIViewController<MyProtocol>  @end 

In your .m:

#import "HopScotch-Swift.h"

From How can I add forward class references used in the -Swift.h header? and the Swift interoperability guide:

If you use your own Objective-C types in your Swift code, make sure to import the Objective-C headers for those types prior to importing the Swift generated header into the Objective-C .m file you want to access the Swift code from.

like image 50
rudd Avatar answered Sep 28 '22 11:09

rudd


I ran into this when trying to use Swift classes inside Objective-C protocols, where the protocol was also implemented by another Swift class. It reeked of circular references and I guessed that it might be a problem trying to circularly generate the bridging headers, rather than a 'normal' circular include problem.

The solution, for me, was to just use forward declarations before the protocol declaration:-

// don't include the MyProject-Swift.h header  // forward declaration of Swift classes used @class SwiftClass;  @protocol MyProtocol <NSObject> - (SwiftClass *)swiftClass; @end 
like image 44
Echelon Avatar answered Sep 28 '22 11:09

Echelon