Integrate a complex Swift Package into your iOS app

I am a Software Engineer working on open source and enterprise mobile SDKs for iOS and MacOS developers written in Swift. From 🇩🇪 and happily living in 🇺🇸
Search for a command to run...

I am a Software Engineer working on open source and enterprise mobile SDKs for iOS and MacOS developers written in Swift. From 🇩🇪 and happily living in 🇺🇸
No comments yet. Be the first to comment.
WWDC26 kicked off on June 8, 2026. The information in this article reflects the information published by Apple on that date. There are 14 new frameworks. Name Description AccessoryAccess Manage

WWDC25 kicked off on June 9, 2025. The information in this article reflects the information published by Apple on that date. New Frameworks NameDescription AlarmKitSchedule prominent alarms and countdowns to help people manage their time. AVR...

WWDC25 is almost here, and I couldn’t be more excited! Whether you're attending the official events, community meetups, or just soaking in the energy around Cupertino, there’s no better time to connect, share ideas, and celebrate everything we love a...

In this blog post, I’ll share an observation and advice regarding the caching behavior of network responses by Apple’s APIs. If you are unfamiliar with caching of network responses then I recommend Apple’s article Accessing cached data that introduce...
WWDC24 kicked off on June 10, 2024. The information in this article reflects the information published by Apple on that date. New Frameworks NameDescription AccessorySetupKitUse AccessorySetupKit to discover accessories with Bluetooth or Wi-Fi...

In this blog post I help app developers to understand the terminology of a Swift Package and how to integrate a more complex structured Swift Package in an iOS application.
The simplest package structure, created by the swift package init command, consists of
The names of all those package/product/target is identical.
Let's look at a more complex example:
// swift-tools-version: 5.6
import PackageDescription
let package = Package(
name: "Package2",
products: [
.library(name: "Package2LibA", targets: ["Package2TargetA"]),
.library(name: "Package2LibB", targets: ["Package2TargetB"]),
],
dependencies: [
.package(path: "../Package1"),
],
targets: [
.target(
name: "Package2TargetA",
dependencies: [.product(name: "Package1Lib", package: "Package1")]),
.target(
name: "Package2TargetB",
dependencies: [.product(name: "Package1Lib", package: "Package1")])
)
]
)
This package (named Package2 here) offers two library products. Each product has its own target. Each target makes use of a library offered by a package dependency.
Let me start explaining the different building blocks from the view of an app developer.

You want to use a library => you add a library product to your app target in Xcode.

Finally, when importing related code from the library => you are using the import <target/module> statement.

In this example the module Package2TargetB offers a public struct API_B.
A Swift target is pretty much equal to a Swift module, so they are often used interchangeably. A module specifies a namespace and enforces access controls on which parts of that code can be used outside of the module.
I highly recommend reading the definition given by Jeremy David Giesbrecht in the Swift Forum. It speaks more to package developers.