# A new access modifier in Swift: package

In this blog post, I'll explain when and where you can use Swift's new `package` access modifier. I'll also give an outlook on plans from Apple to extend its usefulness for closed-code enterprise SDKs.

## Recap: access modifiers you already know

Up until 5.8, there were five different access levels for entities within Swift code.

* `open`
    
* `public`
    
* `internal` (a.k.a *the default*)
    
* `private`
    
* `fileprivate`
    

## New in Swift 5.9: `package`

Apple added a sixth access level, `package`, in Swift 5.9 bundled with Xcode 15.

## Why is it helpful for package developers

When using the Swift Package Manager, you can use this new contextual modifier <mark>to share code between modules within your package without sharing the code outside your package</mark>.

Let's assume I want to develop a Swift package with two modules named `Essentials` and `Utilities`.

| Requirement | Solution |
| --- | --- |
| to make the module `Utilities` accessible outside of this package | declare `Utilities` also as a `library` product |
| allow code reuse of module `Utilities` in `Essentials` while preventing the use of some `Utilities` code outside of this package. | use the `package` access modifier in the `Utilities` module |

```swift
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "SampleSDK",
    products: [
        .library(
            name: "Essentials",
            targets: ["Essentials"]
        ),
        .library(
            name: "Utilities",
            targets: ["Utilities"]
        ),
    ],
    targets: [
        .target(
            name: "Essentials",
            dependencies: ["Utilities"]
        ),
        .target(
            name: "Utilities"
        ),
    ]
)
```

Any types declared with `package` in the `Utilities` module, e.g.

```swift
package func trace()
```

can be accessed from the `Essentials` module

```swift
// this code is part of the `Essentials` module

import Utilities

trace()
```

but not from developers using that package

```swift
// this code is outside of the package

import Utilities

trace() // ERROR !!!!
```

In the package manifest, you can opt-out of the default behavior

```swift
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "SampleSDK",
    products: [
        .library(
            name: "Essentials",
            targets: ["Essentials"]
        ),
        .library(
            name: "Utilities",
            targets: ["Utilities"]
        ),
    ],
    targets: [
        .target(
            name: "Essentials",
            dependencies: ["Utilities"],
            packageAccess: false // <== opt-out !!!
        ),
        .target(
            name: "Utilities"
        ),
    ]
)
```

If you are interested in more details for this new modifier, especially on subclassing and overrides, then you can find such information in the respective Swift evolution proposal document [SE-0386](https://github.com/apple/swift-evolution/blob/main/proposals/0386-package-access-modifier.md).

## Future: Applicability for binary frameworks

Closed-code SDKs often distribute multiple binary frameworks, so it would be great if SDK developers could share code between those frameworks without exposing that code to consumers.

Frameworks of an SDK would need to share the same package name. Looking at the build settings of a framework, you can find a `Package Access Identifier` for exactly that use case 😊

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1704571409914/eab5d935-1334-4c4a-8c93-bb9cee0fa5cf.png align="center")

However, the Swift compiler only supports this concept for packages built from source and otherwise will throw such an error for a binary framework:

> Module 'xyz' is in package 'us.eidinger.MySDK' but was built from interface; modules of the same package can only be loaded if built from source

If Swift can generate an additional `.private.swiftinterface` file for [System Programming Interfaces](https://blog.eidinger.info/system-programming-interfaces-spi-in-swift-explained), then it could also create a `.package.swiftinterface` file. And that's the plan from Apple. I found this promising addition in Apple's Swift main code line to support loading a package interface.

%[https://github.com/apple/swift/pull/69733] 

I am looking forward to a future Swift version that allows SDK developers to support the `package` access modifier in binary frameworks.
