Nested Swift Package Dependencies
Background
As other answers have mentioned, we can import Swift Packages into a project very easy through the File -> Swift Packages -> Add Package Dependency workflow, and that works for the majority of applications. I have added this answer as a further optimisation for packages with nested dependencies.
Swift Packages are imported not just with the Git source code checkout, but also with one, or several Package Products. In my case, I wanted to keep the Package because I used it in one target but not in another target. Sometimes a Package contains multiple dependencies which we don't need, and this is a great opportunity to prune unused dependencies.
Unused imports
I recently made a mistake where I automatically imported all the modules referenced by a Swift Package dependency, even those I don't need. This is common because Packages can have multiple Products which each expose different APIs for different applications.
If you aren't sure if you need an import, check it and delete it. For example, a Package could include an Objective-C Module that adds an additional unnecessary import.
In my case, I imported a Swift Package that was exported via multiple nested libraries: OHHTTPStubs
and OHHTTPStubsSwift
in the above example.
General idea
We can delete nested Swift Package dependencies via Build Phases or the Target General settings tab without deleting the Package itself. Deleting unnecessary dependencies is a good practice to save your app's memory footprint and also streamlines build times.
Nested Dependencies for Unit/UI Testing
Each target should only import the libraries it uses.
Rules:
- Import only the Swift Package Manager Products you actually need when importing for the whole project. Import only the wrapper subspec if that is all you use.
- The Host Application Target doesn't need to import UI testing libraries. We can safely delete these libraries from the Target General tab in Frameworks, Libraries, and Embedded Content. This will automatically unlink the Product from the Build Phases tab for this Target.
- Our UI Testing Target can import the Package Products it needs via Build Phases -> Link Binary with Libraries. If a dependency is only used in UI Tests, delete it from the Host Application Target Frameworks, Libraries, and Embedded Content.
- The Unit Testing Target can't link to libraries that are not embedded in the Host Application. Thus, we need to add products used in Unit Tests to the Host Application Target in the General settings tab for Frameworks, Libraries, and Embedded Content. We DON'T need to add any Products to Link Binary with Libraries for the Unit Tests Target.
Example from my experience
OHHTTPStubsSwift
is the equivalent Swift CocoaPods subspec that adds a nicer API wrapper over the ObjC API but already imports the ObjC API (OHHTTPStubs
).
I deleted the Package Products from the Host Target because I was only using it in UI Tests. I then only imported the OHHTTPStubsSwift
via Build Phases.