with - swift framework private objective c




Objective C classes within an iOS Swift-based dynamic framework (2)

Situation:

I've got an iOS dyanmic framework written in Swift. I've also got a bunch of classes written in Objective C that I would to use within my Swift classes (some are public, some are private). However, I would like the Objective C classes to not be exposed to projects using my framework.


What I have tried:

Umbrella Header

From what I understand, I should import using #import header.h in my umbrella header file, which is usually FrameworkName.h, and then make sure all the Objective C header files that I wish to include in my Swift classes are to marked as "Public", under Build Phases -> Headers.

Doing this, however, automatically exposes the project using my framework to all the private Objective C classes that the framework uses.

Module Mapping (with separate module)

Because of this, I've looked into using module mapping, which is documented here. I've looked at posts by other users such as this and this, as well as this Github repo.

I successfully got the following working:

//SharedClasses/module.modulemap
module SharedClasses {
}

//SharedClasses/module.private.modulemap
module SharedClasses.Private {
    header "header.h"
    export *
}

The problem is that in my project (that has this framework imported), this:

import Framework
import Framework.SharedClasses

is allowed, and subsequently the "hidden" Objective C classes are exposed. Perhaps this is just how modules work? Is there a way to make them truly private?

Module Mapping (with framework private module)

Also, I've tried creating a module.private.modulemap file at the root of my framework with the following contents:

explicit module Framework.Private {
    header "header.h"
    export *
}

and then linking it my target's build settings under MODULEMAP_PRIVATE_FILE. However, when I do import Framework.Private in my framework's Swift classes a compiler error is thrown:

"No such module 'Framework.Private'

I don't understand why this error is occurring.

Module Mapping (with private header)

I noticed that in the Clang docs, a private specifier is mentioned:

A header with the private specifier may not be included from outside the module itself.

My understanding is that since all the Swift classes in my framework are already part of the module Framework, if I create a module.modulemap file with the following:

framework module Framework {
    umbrella header "Framework.h"

    private header "header.h"

    export *
    module * { export * }
}

then everything should be working! The Objective C headers are only accessible within the module (i.e. the framework's Swift classes), and aren't exposed to any project using the framework. Cool, but it doesn't work...the compiler just doesn't recognise the Objective C classes. No other errors are thrown, but you can't use the headers, so it's like you didn't include the headers in the first place. WHY? And what is the private specifier for then?


Soo, reiterating my original question:

Is there any way to import Objective C headers for use in Swift classes, within an iOS dynamic framework, while keeping them private and not accessible from any project using said framework?

Thanks for reading, and sorry for the long post. It's been a long day (and night)...

https://code.i-harness.com


You can find some method from this link.

Just create Folder (e.g.PrivateA) with module.modulemap where include all object headers you need to use in your Swift class. e.g.

module $(ModuleName)Private {
    header "header.h"
    export *
}

in Swift, you can use: import $(ModuleName)Private

so, default module exclude these headers when using import $(ModuleName).

From my experiment, test project can also import $(ModuleName)Private, but not found any useful code.

Try this way anyway.


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