How to Make a Swift Framework Submodule Really Private

How to import private framework headers in a Swift framework?

You need to modify framework A, So that it export a private module.

  1. Create a private module map file in A project. This would be something like this:

    A/private.modulemap:

    explicit module A.Private {

    // Here is the list of your private headers.
    header "Private1.h"
    header "Private2.h"

    export *
    }
  2. In the "Build Settings" of framework A target, search "Private Module Map File" line, and make that:

    $(SRCROOT)/A/private.modulemap
  3. Do not include private.modulemap file in "Compile Sources". That causes unnecessary warnings.

  4. Clean and Build framework A target.

  5. In framework B Swift files. you can import the private module like this:

    import A
    import A.Private

Type extensions from a framework's dependency available in app

I have tried to make use of private module maps to hide the inner framework from being visible to the users of A, but had no luck with it. Could be related to [SR-2896] Private modulemaps do no work properly.

I guess this is the expected behaviour right now. There are multiple proposals on swift.org forums to implement something like you want, for example Namespaces x submodules or a more relevant one @_exported and fixing import visibility.

Relevant parts from the last one:

Today’s Swift is designed more like Java or C# or Python, in that if you import Bar in the implementation of Foo it doesn’t affect clients who import Foo. Or, well, it doesn’t make the top-level names of Bar visible to clients who import Foo.

  1. You still need Bar around, because the compiler doesn’t track whether you’ve used one of its types in Foo’s public interface. (That’s the previous section.)

  2. Extensions in Bar are still made visible to clients who import Foo, because the compiler doesn’t distinguish where extensions come from today.

  3. Operator declarations in Bar are still made visible to clients who import Foo, because the compiler finds operators in a different way than it finds everything else at the top level.

And from one of the last messages:

the general outcome of this discussion is that it's probably not worth doing anything clever for Swift vNext: just add "implementation-only import" and maybe "exported import" and leave the rest alone for now.

I'd be happy to know if there is a workaround for this, but it seems like there is none.

Cocoapods - Swift framework with internal static library dependency

Since you are using a static library as a dependency then you must specify it as a library in your podspec file. Which is why your second approach is not working because it's a library not a source file.

As mentioned in the docs vendored_libraries are for libraries that come shipped with the Pod. Also in your case that C based static library is a dependency which must be shipped with the Pod. Thus using vendored_libraries should be ok in your case.

Path to bundle of iOS framework

Use Bundle(for:Type):

let bundle = Bundle(for: type(of: self))
let path = bundle.path(forResource: filename, ofType: type)

or search the bundle by identifier (the frameworks bundle ID):

let bundle = Bundle(identifier: "com.myframework")


Related Topics



Leave a reply



Submit