CAUTION: This information is mostly obsolete. Xcode 11 allows a project to directly declare its Swift Package Manager dependencies.
This gist walks through creating an Xcode project for an iOS app that consumes packages in Swift Package Manager (SPM).
We'll be using Xcode 10.2 and Swift 5.
We want to create an iOS app named Swifty that consumes PostgresClientKit, a Swift client library for PostgreSQL. PostgresClientKit itself has two dependencies, BlueSocket and BlueSSLService.
We'll create an Xcode workspace containing two projects. The first project, Swifty, is an iOS app created using Xcode. The second project, Dependencies, is a framework created as a library package in SPM that has a dependency on PostgresClientKit (and its dependencies in turn). We then add the Dependencies build products to Swifty as embedded binaries.
Create an empty top-level directory named Swifty.
$ mkdir Swifty
$ cd SwiftyIn Xcode, create a workspace named SwiftyWorkspace.xcworkspace in the Swifty folder.
- File / New / Workspace...
- Navigate to the
Swiftyfolder - Save As:
SwiftyWorkspace.xcworkspace - Save
$ ls -1
SwiftyWorkspace.xcworkspaceIn Xcode, create an iOS project named Swifty.xcodeproj in SwiftyWorkspace.
- File / New / Project...
- Template: iOS
- Application: Single View App
- Next
- Product Name:
Swifty - Next
- Navigate to the
Swiftyfolder - Add to:
SwiftyWorkspace - Create
$ ls -1
Swifty
SwiftyWorkspace.xcworkspace
$ ls -1 Swifty/
Swifty
Swifty.xcodeproj
SwiftyTests
SwiftyUITestsNext, create a Dependencies package in SPM.
$ mkdir Dependencies
$ cd Dependencies
$ swift package init --type library
Creating library package: Dependencies
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/Dependencies/Dependencies.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/DependenciesTests/
Creating Tests/DependenciesTests/DependenciesTests.swift
Creating Tests/DependenciesTests/XCTestManifests.swiftWe can remove some cruft. We need to keep at least one .swift file, but it can be empty.
$ rm -rf README.md Tests Sources/Dependencies/*
$ touch Sources/Dependencies/Placeholder.swift
$ find .
.
./.gitignore
./Package.swift
./Sources
./Sources/Dependencies
./Sources/Dependencies/Placeholder.swift
Now open Package.swift in an editor, and edit the dependencies and targets. It should look like this:
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "Dependencies",
products: [
.library(
name: "Dependencies",
targets: ["Dependencies"]),
],
dependencies: [
.package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "0.0.0"),
],
targets: [
.target(
name: "Dependencies",
dependencies: ["PostgresClientKit"]),
]
)We can now build the package, resolving the dependencies.
$ swift build
Fetching https://github.com/pitfield/PostgresClientKit
Fetching https://github.com/IBM-Swift/BlueSocket.git
Fetching https://github.com/IBM-Swift/BlueSSLService
Completed resolution in 1.94s
Cloning https://github.com/IBM-Swift/BlueSocket.git
Resolving https://github.com/IBM-Swift/BlueSocket.git at 1.0.46
Cloning https://github.com/IBM-Swift/BlueSSLService
Resolving https://github.com/IBM-Swift/BlueSSLService at 1.0.46
Cloning https://github.com/pitfield/PostgresClientKit
Resolving https://github.com/pitfield/PostgresClientKit at develop
[4/4] Compiling Swift Module 'Dependencies' (1 sources)And then generate an .xcodeproject.
$ swift package generate-xcodeproj
generated: ./Dependencies.xcodeprojBack in Xcode, let's add that new Xcode project to our workspace.
- In the Project Navigator, right-click on the background. Select "Add Files to SwiftyWorkspace...".
- Navigate to the
Dependenciesfolder and selectDependencies.xcodeproj - Add
We can remove some unneeded schemes.
- Product / Scheme / Manage Schemes...
- Delete all the schemes except
Swifty - Close
We can remove some unneeded targets.
-
In the Project Navigator, select the
Dependenciesproject -
In the editor, remove all targets whose names end in
PackageDescription:DependenciesPackageDescriptionPostgresClientKitPackageDescriptionSSLServicePackageDescriptionSocketPackageDescription
Four targets should remain:
DependenciesPostgresClientKitSSLServiceSocket
Finally, we embed the dependencies in Swifty.
- In the Project Navigator, select the
Swiftyproject - In the editor, select the General tab
- On that tab, click "+" in Embedded Binaries
- Select all four dependencies under Dependencies / Products (they may be in a different order):
Dependencies.frameworkPostgresClientKit.frameworkSSLService.frameworkSocket.framework
- Add
Building Swifty should now bring in all the dependencies.
- In the toolbar, confirm the
Swiftyscheme is selected - Product / Build
Open AppDelegate.swift. Import PostgresClientKit.
import PostgresClientKitIn application(_:didFinishLaunchingWithOptions), set the Postgres log level, then log a message. Code completion should work.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Postgres.logger.level = .info
Postgres.logger.info("Log level set to \(Postgres.logger.level)")
return true
}Run the app on a simulator or a device. You should see the logged message in the console (View / Debug Area / Activate Console).
Success!