Hi Switers :), Today, we are going to explore a handy little feature in Swift. Lets say you are packing for a vacation but instead of packing just for yourself, you decide to pack extra clothes and snacks in case your friend forgets theirs. Generous, right? Well in Swift there’s a feature that does something kind of like that for imports. Its called the @_exported import
its a powerful tool to help make your code more modular and DRY.
The Problem: Repeating Yourself with Imports
Let’s say you’re building a Swift module or an internal framework. And inside this framework, you’re using a dependency like Alamofire
or UIKit
. Now imagine that you have multiple files importing your framework
import MyNetworkingLib
import Alamofire // still need this manually
Even though MyNetworkingLib
uses Alamofire under the hood, your app code still needs to manually import Alamofire
if it wants to use any of its symbols. Thats kind of annoying, right? It’s like bringing your own fork to a restaurant even though they clearly use forks inside 😀
So What Is @_exported import
?
The @_exported import
declaration tells Swift:
“Hey, not only am I using this module I want to re-export it too. So anything that imports me also gets this one, automatically.”
Think of it like:
- Normal
import
: You’re keeping it to yourself. @_exported import
: You’re sharing it with everyone who uses you.
Basic Syntax
@_exported import Alamofire
Now, anywhere that imports your module will also implicitly get Alamofire
. No need to import it separately. Lets take a look at real world example, let’s say you are building a Swift package called MyNetworkingLib
. You are using Alamofire inside it.
Before: Without Exporting
// In MyNetworkingLib.swift
import Alamofire
public func makeRequest() {
AF.request("https://thepenguin.tech")
}
Then, in your app:
import MyNetworkingLib
import Alamofire // required if you want to use `AF` directly
Even though you use AF
inside your library, anyone using your library still has to import Alamofire
directly. Kind of defeats the purpose of abstraction.
After: With @_exported import
// In MyNetworkingLib.swift
@_exported import Alamofire
public func makeRequest() {
AF.request("https://thepenguin.tech")
}
Now, in your app:
import MyNetworkingLib
AF.request("https://another.com") // ✅ works!
No need to import Alamofire again because it’s exported through your library!
So Where Is This Actually Useful
- Frameworks that wrap or depend heavily on other libraries
- Modules that compose multiple smaller modules into one
- Internal SDKs where you want to simplify your public API
- Avoiding repeated imports across multiple files
But Wait, Why Is It Underscored?
You might’ve noticed: it’s @_exported import
, not @exported import
. That underscore means it’s a compiler attribute and technically not officially public API. It’s available and works well, but Apple might reserve the right to change or formalize it in the future. That said, it’s been around for years and is widely used in real projects (especially internal frameworks and packages). So it’s considered stable enough for practical use but don’t be surprised if it evolves into a cleaner exported import
someday.
Be Careful With Overexposure
While this tool is powerful, don’t get too export happy. You don’t want to leak every dependency your library uses. Ask yourself this:
- Do consumers need direct access to this module?
- Or can they just use your public API without knowing what’s underneath?
Only export what you want others to rely on directly.
So that was brief guide about @_exported import. I hope you liked it. Stay tuned for more interesting content about Swift and iOS development.
Make sure to follow us on so that you don’t miss any updates: Twitter/X, and LinkedIn