1

I have been creating Internal (local) Swift Packages and then creating frameworks that import those packages as modules to help create service providing [public] classes and structs.

Said frameworks are then imported into the main app Xcode project and it's been working very well to manage / modularize a very large code base.

1. If I am creating an Xcode Project should it have its own scheme?

2. Should the scheme container of the project being the main app project?

3. Is there a better way to go about this or am I doing this in the most widely accepted way possible (industry standard, if you will)?

3 Answers3

1

Schemes are target specific, so each target in your project needs to have its own scheme.

To compile your packages into your final solution, technically you'll only need the schemes for the targets of your projects, i.e. for the frameworks you're compiling.

That said, most likely your packages already contain some test targets, which would need their own schemes to run. Though technically these schemes could be created in your main project, they should be created on the lowest level the targets can be build and tested.

DatBlaueHus
  • 266
  • 1
  • 5
1

SPM for Modularized code

I think you're on the right track. Though I think it's simpler than you may think it is. There is no need to make frameworks to consume your swift packages before your app can consume them. I have a project with 12 local Swift Packages to modularize the code. No frameworks. Only 1 scheme. No hassle.

Baseline

Before I try to answer this question—since it's a bit involved—I want to start by laying a baseline that describes a very simple app with no dependencies for starters.

Imagine you just created a project and your file structure looks a bit like this:

RootDirectory/
    MyProject.xcodeproj
    MyProject/
        MyProjectApp.swift
        ContentView.swift
        Info.plist
        Assets.xcassets/

Create a Package

I generally stay away from creating my local swift packages within Xcode. I do it from the command line like so:

# Travel to the project's root directory
cd path/to/RootDirectory

# Create a directory to host the new package
mkdir MyPackage

# Move to the new directory
cd MyPackage

# Create the new Swift Package
swift package init

After that is done, the directory structure should look like this:

RootDirectory/
    MyPackage/
        Package.swift
        Sources/
        Tests/
    MyProject.xcodeproj
    MyProject/
        MyProjectApp.swift
        ContentView.swift
        Info.plist
        Assets.xcassets/

My Package.swift file looks like this:

// swift-tools-version:5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "Core",
    platforms: [.iOS(.v15), .macOS(.v12), .watchOS(.v8), .tvOS(.v15)],
    products: [
        .library(
            name: "Core",
            targets: ["Core"]),
    ],
    dependencies: [],
    targets: [
        .target(
            name: "Core",
            dependencies: []),
        .testTarget(
            name: "CoreTests",
            dependencies: ["Core"]),
    ]
)

Consume the Local Package

After that is done, I would add the package to the App's Xcode Project like so:

Add Package Select Local Package

After you've added the package, you want to make sure it shows up in the Linked Libraries area of the App Target's Build Phases:

Linked Libraries Section

Then, make sure your app target's scheme knows to include your packages for building and/or testing like so:

App Scheme

Result

You can do that over and over again. Your project should look something like this at the end:

List of Local packages

Jake
  • 2,126
  • 1
  • 10
  • 23
  • Happy to help if you have questions, though I'm not on Stack Overflow much. So, please be patient :D – Jake Jul 30 '22 at 03:11
0

You can create a pod file for your own framework. It’s very simple and easy to use for other projects. And versioning also easy.

Emre Agbal
  • 109
  • 1
  • 4