I have an Objective-C project with 1 Swift class. This class is using a framework that is also written in Swift. (Used CocoaPods to include the framework)
My problem is that the -Swift.h file is exporting my extensions that adhere to protocols in the framework. Now when I try to import the -Swift.h file in the Objective-C, it complains that that the protocol definitions cannot be found.
I don't want these extensions exported. They are only used in this class. I can't use private or fileprivate for extensions that declare protocol conformances. I also tried adding @nonobjc before the extension declaration (which cascaded warnings into my methods) and it was still exported.
Here are my extensions:
extension MessagingExperience: MessagingDelegate {
...
}
extension MessagingExperience: MessagingNotificationDelegate {
...
}And generated header:
@interface MessagingExperience (SWIFT_EXTENSION(Reference_App)) <MessagingDelegate>
- (void)MessagingObseleteVersion:(NSError * _Nonnull)error;
- (void)MessagingError:(NSError * _Nonnull)error;
@end
@interface MessagingExperience (SWIFT_EXTENSION(Reference_App)) <MessagingNotificationDelegate>
- (BOOL)shouldShowMessagingNotificationWithNotification:(MessagingNotification * _Nonnull)notification SWIFT_WARN_UNUSED_RESULT;
- (void)messagingNotificationTapped:(MessagingNotification * _Nonnull)notification;
- (UIView * _Nonnull)customMessagingNotificationViewWithNotification:(MessagingNotification * _Nonnull)notification SWIFT_WARN_UNUSED_RESULT;
@endErrors produced by including the -Swift.h in an Objective-C class:
Cannot find protocol declaration for 'MessagingDelegate'
Cannot find protocol declaration for 'MessagingNotificationDelegate'
Is there a way to prevent this from being in the header?
Thanks.
I found three statements in the official Swift docs that seem to have some relevance here. The first 2 are from
under "Importing Code from Within the Same App Target" -> "Importing Swift into Objective-C":
[1] "By default, the generated header contains interfaces for Swift declarations marked with the public or open modifier. It also contains those marked with the internal modifier if your app target has an Objective-C bridging header."
[2] "Note that the Swift interfaces in the generated header include references to all of the Objective-C types used in them. If you use your own Objective-C types in your Swift code, make sure to import the Objective-C headers for those types before importing the Swift generated header into the Objective-C .m file"
and the third is from
under "Access Control" -> "Extensions":
[3] "You can’t provide an explicit access-level modifier for an extension if you’re using that extension to add protocol conformance. Instead, the protocol’s own access level is used to provide the default access level for each protocol requirement implementation within the extension."
The statements are not very specific, but #3 suggests to me that you should be able to get rid of the errors by @import'ing the framework into your Obj-C code that uses the MessagingExperience class.
#1 and #2 also suggest to me that the reason the protocols are being exposed in the generated header is that they are (I'm guessing) declared public in the framework, and Swift currently has an unresolved design issue where are class that conforms to a public protocol cannot conform to it privately (i.e. without advertizing its conformance).
One workaround might be to add the protocol conformance to a private subclass of MessagingExperience, and using that subclass internally in the Swift code. The objects can still be shared with Obj-C code. All you need to do (as a safety check) is make sure that instances of the base class can't be created directly.
If no one else jumps in with a more straightforward answer, you should probably ask this question over of the "swift-users" mailing list at swift.org. The answer may require the expertise of the Swift team to say exactly what it causing your problem, and whether there's a fix.