# Mixing Swift and Objective-C in a framework and private headers

**URL:** <https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787>\
**Category:** Using Swift\
**Created:** [August 10, 2019, 6:54pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787 "2019-08-10T18:54:57Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [August 10, 2019, 6:54pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/1 "2019-08-10T18:54:57Z")

</div>

We're having an Objective-C framework that exposes a bunch of classes and also has private helper functions in categories. For example:

- `MyObject.h`:

```swift
#import <Foundation/Foundation.h>
@interface MyObject : NSObject {
- (void)publicMethod; 
}

```

- `MyObject+Private.h:`

```swift
#import "MyObject.h"
@interface MyObject (Private) {
- (void)internalOnlyMethod;
}

```

- `MyFramework.h`:

```swift
#import <MyObject.h>

```

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:

```swift
framework module MyFramework {
	umbrella header "MyFramework.h"

	export *
	module * { export * }

	explicit module Private {
		header "MyObject+Private.h"
	}
}

```

Unfortunately, the swift compiler complains about not being able to find the filer for `#import "MyObject.h"` .

Anyone got this to work? Are we doing some wrong?

---

<div class="post-metadata">

**Author:** ![jonprescott](https://avatars.discourse-cdn.com/v4/letter/j/e36b37/32.png) [@jonprescott](https://forums.swift.org/u/jonprescott)\
**Post date:** [August 10, 2019, 7:50pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/2 "2019-08-10T19:50:47Z")

</div>

What about bridging headers, if the Swift code is part of the framework?

---

<div class="post-metadata">

**Author:** ![jonprescott](https://avatars.discourse-cdn.com/v4/letter/j/e36b37/32.png) [@jonprescott](https://forums.swift.org/u/jonprescott)\
**Post date:** [August 10, 2019, 7:54pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/3 "2019-08-10T19:54:54Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [August 10, 2019, 8:32pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/4 "2019-08-10T20:32:31Z")

</div>

Bridging Headers are unsupported inside frameworks unfortunately. (The swift code is part of the framework).

---

<div class="post-metadata">

**Author:** ![Colin\_Cornaby](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/colin_cornaby/32/8243_2.png) [@Colin\_Cornaby](https://forums.swift.org/u/Colin_Cornaby)\
**Post date:** [August 17, 2019, 5:40am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/5 "2019-08-17T05:40:09Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Prasanna](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/prasanna/32/12923_2.png) [@Prasanna](https://forums.swift.org/u/Prasanna)\
**Post date:** [October 14, 2019, 5:12pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/6 "2019-10-14T17:12:45Z")

</div>

Hello,

Is there any update regarding this?. Anyone know how to make this work?.

---

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [October 17, 2019, 9:58am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/7 "2019-10-17T09:58:34Z")

</div>

We finally had success in Xcode 11 using:

- add a custom `MyFramework.modulemap`

```swift
framework module MyFramework {
	umbrella header "MyFramework.h"
	export *

	explicit module Private {
           header "MyPrivateHeader.h"
           header "MyPrivateOtherHeader.h"
        }
}

```

- 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

---

<div class="post-metadata">

**Author:** ![Prasanna](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/prasanna/32/12923_2.png) [@Prasanna](https://forums.swift.org/u/Prasanna)\
**Post date:** [August 14, 2020, 8:11pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/8 "2020-08-14T20:11:35Z")

</div>

@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`.

---

<div class="post-metadata">

**Author:** ![Prasanna](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/prasanna/32/12923_2.png) [@Prasanna](https://forums.swift.org/u/Prasanna)\
**Post date:** [August 18, 2020, 5:57pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/9 "2020-08-18T17:57:01Z")

</div>

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?.

---

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [August 21, 2020, 11:59am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/10 "2020-08-21T11:59:43Z")

</div>

Is that in ObjC or Swift?

---

<div class="post-metadata">

**Author:** ![Prasanna](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/prasanna/32/12923_2.png) [@Prasanna](https://forums.swift.org/u/Prasanna)\
**Post date:** [August 21, 2020, 1:10pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/11 "2020-08-21T13:10:00Z")

</div>

@DeskA I am not sure whether your question is about my first question or second but here is some more context,

1. 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.

2. The error `@import of module ‘MyFramework.Private’ in implementation of ‘’MyFramework”` is from [MyFramework-Swift.h](https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c#3024308) (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.

Here is a [stack overflow question](https://stackoverflow.com/questions/38078999/swift-import-of-module-module-name-in-implementation-of-project-name-use) describing this exact problem. Unfortunately the accepted answer in there suggests avoiding private modules and making every objective c file public.

---

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [August 21, 2020, 3:49pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/12 "2020-08-21T15:49:52Z")

</div>

Is there a chance you are importing private headers in one of the public header files in your ObjC framework?

---

<div class="post-metadata">

**Author:** ![andrejordan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andrejordan/32/13280_2.png) [@andrejordan](https://forums.swift.org/u/andrejordan)\
**Post date:** [September 29, 2020, 4:30pm UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/13 "2020-09-29T16:30:52Z")

</div>

hey @DeskA! This is great. Do you have any tips on how to set up the Linter rule? That's the only part I'm kind of stuck on.

Thanks so much!

---

<div class="post-metadata">

**Author:** ![DeskA](https://avatars.discourse-cdn.com/v4/letter/d/b77776/32.png) [@DeskA](https://forums.swift.org/u/DeskA)\
**Post date:** [September 30, 2020, 11:14am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/14 "2020-09-30T11:14:15Z")

</div>

We simply have a regex for `import OurFramework.Private` and friends :)

---

<div class="post-metadata">

**Author:** ![doozMen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/doozmen/32/7803_2.png) [@doozMen](https://forums.swift.org/u/doozMen)\
**Post date:** [March 14, 2022, 9:17am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/15 "2022-03-14T09:17:10Z")

</div>

A working github project is here [GitHub - danieleggert/mixed-swift-objc-framework: Shows how to mix Swift and Objective-C code inside a framework target](https://github.com/danieleggert/mixed-swift-objc-framework) that allows import of private headers

---

<div class="post-metadata">

**Author:** ![MrKang](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mrkang/32/45647_2.png) [@MrKang](https://forums.swift.org/u/MrKang)\
**Post date:** [June 13, 2026, 6:49am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/17 "2026-06-13T06:49:01Z")

</div>

Even in 2026, I’ve found that this is still a problem many developers don’t know how to solve. First of all, if you don’t want certain headers to be exposed, you shouldn’t use a private module, because a private module will always be exposed.

The simplest approach is that you don’t need to customize the framework’s `module.modulemap`. Just create a `module.modulemap`file in the same directory as the headers that should only be visible within the framework.

```swift
module PrivateModuleName {
    header "XXX.h"

    export *
}

```

```swift
@_implementationOnly import PrivateModuleName

class A {
    // .....
}

```

Create a `module.modulemap` file in the same directory as the header to compile and use the header as a Clang module. Swift can then import this module normally and access the Objective-C code within it.

However, since this module is not added to the Build Phases, it is not included in the final framework artifact.Add `@_implementationOnly` before the import statement. This ensures that even when `BUILD_LIBRARY_FOR_DISTRIBUTION` is set to `true`, the dependency will not be exposed in the generated `.swiftinterface` file, preventing consumers of the framework from encountering errors about a module that doesn’t actually exist.

---

<div class="post-metadata">

**Author:** ![ian.hein](https://avatars.discourse-cdn.com/v4/letter/i/2acd7d/32.png) [@ian.hein](https://forums.swift.org/u/ian.hein)\
**Post date:** [June 17, 2026, 6:40am UTC](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/18 "2026-06-17T06:40:04Z")

</div>

Hi, @MrKang . I tried your scheme but the compiler could not find this PrivateModuleName, could u plz provide more details? Thanks a lot
