How to Add a Swift Package Dependency in Xcode

Learn how to add, configure, and manage third-party libraries in your iOS project using Swift Package Manager built directly into Xcode.

Why Use Swift Package Manager

Most real iOS apps rely on third-party libraries for networking, analytics, UI components, and more. You rarely want to build everything from scratch.

Swift Package Manager (SPM) is Apple's official dependency manager, and it is built directly into Xcode. There is nothing extra to install.

That tight integration is the main advantage. You add a package through Xcode's interface, and it handles fetching, versioning, and linking for you.

This guide shows how to add a package, choose a version rule, import it in code, and manage it over time.

Step 1: Open the Package Dependencies Screen

Open your project in Xcode and select the project file at the top of the navigator.

In the editor, select the project (not a specific target) and open the Package Dependencies tab. This is where all your SPM dependencies are listed.

Alternatively, you can use the menu: File > Add Package Dependencies. Both routes lead to the same package search and add dialog.

This screen is your central place to add new packages, update existing ones, and remove dependencies you no longer need.

Step 2: Enter the Package URL

In the add-package dialog, paste the Git repository URL of the package you want, usually a GitHub HTTPS URL ending in .git or the plain repository address.

Xcode contacts the repository and reads its package manifest. Within a moment you should see the package name and its available versions.

Make sure you trust the source. Adding a dependency means running and shipping someone else's code, so prefer well-maintained, reputable packages.

If the URL is private, you may be prompted to authenticate with the appropriate Git credentials or an access token.

Step 3: Choose a Version Rule

Xcode lets you pin the dependency using a dependency rule. The most common choice is Up to Next Major Version, which accepts compatible updates while avoiding breaking changes.

You can also pin to an exact version, a version range, a specific branch, or a particular commit. Exact versions give maximum reproducibility; branches give the latest code but less stability.

For most apps, a major-version rule strikes a good balance between staying current and avoiding surprise breakage.

Pick the rule that matches your risk tolerance, then click to proceed. Xcode resolves the dependency graph and downloads the package.

Step 4: Add the Package Product to Your Target

After resolution, Xcode shows the library products the package provides. Check the boxes for the products you want and assign each to the correct app target.

Most packages expose a single library product, but some offer several. Add only the ones you actually need to keep your build lean.

Confirm the target is your main app (or the specific target that needs the library). If you have multiple targets, repeat as needed.

Click Add Package to finish. Xcode links the library and updates your project so the code is available to import.

Step 5: Import and Use the Library

Open the Swift file where you want to use the dependency and add an import statement at the top, using the module name the package provides.

The module name is usually the product name shown when you added the package, which may differ slightly from the repository name.

Once imported, the package's public types and functions become available with code completion. Build the project with Command-B to confirm everything links correctly.

If the import is not recognized, do a clean build and make sure the package product was added to the correct target.

Step 6: Manage and Update Dependencies

Over time you will want to update packages. In the Package Dependencies area, Xcode can resolve to newer versions allowed by your version rules.

Use File > Packages > Update to Latest Package Versions to pull in updates within your rules, or reset the package cache if resolution gets stuck.

Xcode records resolved versions in a Package.resolved file. Commit this file to source control so your whole team builds against identical versions.

To remove a dependency, select it in the Package Dependencies list and delete it, then remove any related import statements from your code.

How SPM Compares to Other Tools

Before Swift Package Manager matured, many iOS projects used CocoaPods or Carthage to manage dependencies. Both are still found in older codebases.

CocoaPods is a long-standing dependency manager that integrates through a separate workspace and a Podfile, and it has a huge library of supported packages.

Carthage takes a more hands-off approach, building dependencies into frameworks that you link manually, which gives control at the cost of extra setup.

SPM's advantage is that it ships inside Xcode with no extra installation, no Ruby gems, and no separate command-line setup for the common case. For new projects, it is usually the path of least resistance, though you may still encounter the others when working on existing apps.

Understanding Versions and Resolution

When you add a package, Xcode does more than download files. It resolves a dependency graph, figuring out which versions satisfy every rule across all your packages.

If two packages disagree about a shared dependency's version, resolution can fail, and Xcode will report that it could not find compatible versions.

The Package.resolved file is the record of exactly which versions were chosen. Treat it like a lockfile: it pins the resolved state so every build is reproducible.

When you intentionally want newer versions, use the update command in the Packages menu rather than editing Package.resolved by hand. Letting Xcode re-resolve keeps the whole graph consistent.

Troubleshooting Resolution Problems

Dependency resolution does not always go smoothly, especially in larger projects. A few patterns cover most failures.

If Xcode reports that it cannot resolve versions, two of your packages likely require incompatible versions of a shared dependency. Loosening or aligning your version rules often clears it.

When a package seems stuck or out of date, resetting the package cache and resolving again forces Xcode to fetch fresh state. This is in the Packages menu under the File menu.

Network and authentication issues are also common with private repositories. Confirm your Git credentials or access token are valid, since a failed fetch can look like a resolution error even when the rules are fine.

Best Practices and Cautions

Keep your dependency count reasonable. Every package adds build time, potential security surface, and maintenance burden.

Prefer packages that are actively maintained and widely used. Check the repository's recent activity and issue history before committing.

Pin sensibly. Major-version rules are fine for most cases, but for critical apps you may want exact versions for full reproducibility.

Finally, always commit Package.resolved. It is what guarantees that you and your CI system build with the same dependency versions, avoiding the classic 'works on my machine' problem.

Frequently Asked Questions

Is Swift Package Manager built into Xcode?

Yes. SPM is Apple's official dependency manager and is integrated directly into Xcode, so you can add packages without installing any separate tool.

What version rule should I choose?

For most apps, Up to Next Major Version is a good default. It accepts compatible updates while avoiding breaking changes. Use exact versions when you need full reproducibility.

Should I commit Package.resolved to source control?

Yes. Committing Package.resolved ensures your team and CI build against identical dependency versions, preventing inconsistent builds.

Why isn't my import recognized after adding a package?

Confirm the package product was added to the correct target, use the module name (not always the repo name), and try a clean build with Shift-Command-K followed by a rebuild.