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

自古美人都是妖i 提交于 2021-02-08 07:46:36

问题


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?


回答1:


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.




回答2:


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



回答3:


The forward declaration by itself didn't work for me. It compiled without errors but still had warnings that the protocol couldn't be found. I treat all warnings as errors, so this isn't good enough.

I was able to fix it by moving the protocol implementation into another category header.

So here's what worked for me:

In my MyOtherSwiftFile.swift:

@objc protocol MyProtocol: class {
func viewController(didFinishEditing viewController: MyViewController)
}

In my MyViewController.h:

@interface MyViewController // Removed protocol implementation declaration here
@end

Added MyViewController+MyProtocol.h to project, and put this in there:

@interface MyViewController (MyProtocol) <MyProtocol>
@end

The methods themselves can stay where they are if you want.

After you implement the above and compile, you'll get compiler warning(s) somewhere in your code that requires that MyViewController implements MyProtocol. In that file, you will #import "MyViewController+MyProtocol.h"




回答4:


You could something like this in the .h file you suspect to trigger the circular reference:

#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif


来源:https://stackoverflow.com/questions/44761658/how-to-reference-swift-protocol-from-objective-c-header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!