The private functionality is only used inside of the framework and we don't want to expose it publicly. Currently, we do that by having MyObject.h be a public header and inside the umbrella header for the framework and MyObject+Private.h be a private or project header. This works fine in Objective-C.
We're currently trying to add some swift to this framework: this works, except that our swift code doesn't have access to the internal/private functionality, since they are not exposed thru the umbrella header.
The common suggestion seems to be using a private module map, but this is very under-documented. We cannot get it to work without the swift compiler spitting our errors:
I think the module map only plays a role when importing a framework. If your Swift code is importing MyFramework, then it is a consumer of MyFramework, and one needs to look at whether the Swift code should be using the private methods. If the Swift code is part of the framework, I think you need to use the bridging headers to make Objective-C code callable by Swift.
I've been banging my head against this as well. We want to start adding Swift extensions to our Obj-C classes, but if any of our extensions require access to private functions, we can't call them.
There are other issues this creates too beyond Obj-C. If you have a private C (or eventually C++ function) you also can't use a bridging header to get at those functions. This means even if we rewrite entirely in Swift we're going to hit some core libraries we can't call.
I haven't gotten module maps to work either, and I'd be curious if anyone got them to work successfully. Most cases I've read online that got them working found that anything in the module map got added to the public framework interface anyway, defeating the purpose. The private module map just gets added as a dependency for the public one.
It's a pretty serious issue, especially if you want to start migrating a framework piecemeal to Swift or add functionality based on Swift only API like Combine.
We've also had some success declaring protocols with our private functions within our Swift code on AnyObject, and then casting objects to call into private functions (bleh) to call from Swift into Obj-C. To call from Obj-C into Swift, I just handwrite a private header representing the Swift API. While annoying, that seems to work without a lot of mess, as long as you keep the handwritten header and API in sync.
Mark all private headers as "Private", instead of "Project" inside your framework
In your swift file, you can now import MyFramework.Private
To stop users of the framework from importing private stuff, we added a linter rule that errors on import MyFramework.Private while not being inside the framework project
Be aware that for this approach to work, you must import headers using < > brackets instead of quotes inside the (Obj-)C files in your framework. So, #import <MyFramework/MyPublicHeader.h> and #import <MyFramework/MyPrivateHeader.h>
We also tried this with Xcode 10, but that would either crash the compiler or result in a barrage of errors
@DeskA With the setup that you mentioned private header classes are automatically being accessible even without import MyFramework.Private in the client project.
Is that what you are experiencing too?. I noticed that all the private headers being placed in the PrivateHeaders folder of the framework build but I am not sure those classes are accessible without an explicit import of MyFramework.Private.
Also when I follow the above instructions, I am getting error @import of module âMyFramework.Privateâ in implementation of ââMyFrameworkâ; use #import from MyFramework-Swift.h file, have you seen that error before?. Am I doing something wrong here?.
@DeskA I am not sure whether your question is about my first question or second but here is some more context,
My framework's client project is in Swift, and in that client project all the private headers are being exposed even without the import MyFramework.Private. At this moment I am not worried about this issue. It would be nice to have a solution for this though.
The error @import of module âMyFramework.Privateâ in implementation of ââMyFrameworkâ is from MyFramework-Swift.h (which is auto-generated by Xcode). I am using this file to use newly written swift code in existing objective-c within the framework itself. Basically due to the nature of our large framework project, we need to import the swift code into objective-c and objective-c code into swift and we are trying to gradually convert code over to swift.
For importing swift code into objective-c we are using this MyFramework-Swift.h
For importing objective-c into swift I am trying to use the private submodule approach that you mentioned and running into this error in the following sequence.
I think the compiler is trying to compile an objective-c file which has in import like #import <MyFramework/MyFramework-Swift.h>
And in that auto generated file it has @import MyFramework.Private, which is causing this error.
Here is a stack overflow question describing this exact problem. Unfortunately the accepted answer in there suggests avoiding private modules and making every objective c file public.