---
title: Framework with hidden dependencies
slug: framework-with-hidden-dependencies
docTags: 
createdAt: 2021-02-12T17:19:51.000Z
---

When developing a framework other developers will use, we may need to include another framework to ours as a dependency. If we use the included framework just for the implementation details, we don't want it to be visible (re-export) to the developers that integrate our framework in their app.

That's why we need to find a way to “hide” internal dependencies from the clients of our framework. This is something that is being discussed over Swift Forums, and currently it's partly implemented, but Apple does not officially support it. It may introduce breaking changes in future versions of Swift.

## How to follow up

We have three separate pieces that we will mention through the article.

1. Framework that we are developing for the clients — **OurFramework&#xA0;**
2. Framework that we are including in our framework as dependency — **FrameworkA&#xA0;**
3. Client's app that integrates our framework — **ClientApp&#xA0;**

![](https://archbee-doc-uploads.s3.amazonaws.com/VU9phOpDtRwSx5Irpi731/J8QM5MiLYX3RyVezxVVdj_image.png)

# Integrate FrameworkA

We will do it manually with no dependency manager to make it transparent what we are doing.

1. Drag and drop **FrameworkA.xcframework** to the **OurFramework** project
2. `import FrameworkA` somewhere in **OurFramework** code

And that would be it, right? Well, not exactly, let's export **OurFramework.xcframework** and try to use it from the test project. Xcode won't build the test project because it fails with the following error.

:::hint{type="danger"}
Failed to build module 'OurFramework' from its module interface; it may have been damaged, or it may have triggered a bug in the Swift compiler when it was produced
:::

## Failed to build module

1. Click on **OurFramework** in folder structure in Xcode. 
2. Select **Build Settings** tab. 
3. Set **Framework Search Paths&#xA0;**&#x74;o the directory where **FrameworkA.xcframework** is located. 
4. Export **OurFramework.xcframework** again and add it to the test project.

This time there are no errors and the project builds. But the problem is that now we can import included **FrameworkA** as well, which may not be behavior that we want.

## Framework visibility

:::hint{type="warning"}
⚠️ As already mentioned in introduction, this is not fully supported by Apple and may be buggy as stated in https\://forums.swift.org/t/update-on-implementation-only-imports/26996.
:::

If we want to hide the framework that is included in your framework as dependency for whatever reason we need to import the included framework differently. Instead of standard `import FrameworkA` we need to use `@_implementationOnly import FrameworkA`.

1. Add `@_implementationOnly` annotation to the imports of **FrameworkA.&#xA0;**

```swift
// MyFramework.swift
@_implementaitonOnly import DependencyFramework

```

1. Export **OurFramework.&#xA0;**
2. Add **OurFramework** to the test project.

Now if we try import FrameworkA in the test project, Xcode will throw an error that it can't find the module **FrameworkA**. 

***

By using `@_implementationOnly import`, **FrameworkA** won't be added to the swiftinterface file.

Quote from [Harlan Haskins](https://twitter.com/harlanhaskins) from [Swift forums post](https://forums.swift.org/t/challenges-creating-an-xcframework-for-native-libraries/41600).

:::BlockQuote
This is where the somewhat-unsupported-but-still-very-useful @\_implementationOnly import comes in -- @\_implementationOnly import X hidden the import of X from your clients (one way that it does this is by not printing the import in the .swiftinterface file)It also requires that you do not use the types from X in any of your public API or ABI surface, since that would require your clients to be able to see into X. And without library evolution turned on, using any type from X inside any of your public types, even if they're private, means they're part of your type's ABIs. The safest thing is to combine @\_implementationOnly import with library evolution for your framework. And since declarations in @\_implementationOnly imported libraries are *not* part of your library's ABI, those libraries do not need to maintain ABI stability or be compiled with library evolution support.
:::

### Limitations

- Public API of **OurFramework** can't use any API from **FrameworkA&#xA0;**—**&#xA0;**&#x65;nforced by the compiler. 
- Public types of **OurFramework** can't conform to the protocols of **FrameworkA** — enforced by the compiler. 
- If the public type of **OurFramework** overrides type from **FrameworkA**, we must use `@_implementationOnly` annotation on that public type as well. 
- `@testable import MyFramework` can be buggy because it does not include **OurFramework** as it would normally do without `@_implementationOnly`.

# References

- [https://forums.swift.org/t/challenges-creating-an-xcframework-for-native-libraries/41600](https://forums.swift.org/t/challenges-creating-an-xcframework-for-native-libraries/41600)
- [https://forums.swift.org/t/update-on-implementation-only-imports/26996/17](https://forums.swift.org/t/update-on-implementation-only-imports/26996/17)
- [https://forums.swift.org/t/exported-and-fixing-import-visibility/9415](https://forums.swift.org/t/exported-and-fixing-import-visibility/9415)
- [https://medium.com/@anuragajwani/modular-ios-guide-60810f5a7f97](https://medium.com/@anuragajwani/modular-ios-guide-60810f5a7f97)

