Modularization
Divide your App into independent modules.
Modularization
Divide your App into independent modules.
0
0
Checkbox to mark video as read
Mark as read

Xcode provides powerful tools for organizing and reusing code through frameworks and packages. While frameworks offer a way to bundle code, resources, and assets into a reusable module, the Swift Package Manager (SPM) simplifies the process of sharing and integrating Swift code. This guide will cover the basics of frameworks and packages in Xcode and provide step-by-step instructions on creating your own Swift package library that you can upload to GitHub for public or private use.

Frameworks and Packages: What’s the Difference?

In Xcode, frameworks and packages help modularize code, making it reusable and easy to maintain. Here’s a quick overview:

  • Frameworks: A framework is a bundle containing compiled code and resources that developers can reuse across different apps. Common frameworks include UIKit and Foundation. In iOS, developers often create frameworks to encapsulate complex functionality for specific features.
  • Packages: Swift Packages are collections of Swift code managed by the Swift Package Manager. Packages can be shared, versioned, and integrated with projects easily. With the growing popularity of SPM, creating packages is now a standard way to distribute reusable code in the Swift community.

Creating Your Own Swift Package

For this example, we are going to create a package that will contain a Networking Client that we could import and use in all of our new projects:

Step 1: Create a New Swift Package

  1. Open Xcode and select File > New > Package.
  2. Select Library
  3. Select the test system you'd like.
  4. Give your package a name. This will be the name others will use to import it, so choose a name that reflects its functionality.
  5. Choose a location to save your package, then click Create. Xcode will create a new folder containing the package’s structure, including the Package.swift file.

The Package.swift file is the package’s manifest file, which defines the package name, its dependencies, targets, and other metadata. It’s automatically created with default values.

Step 2: Define Your Package’s Structure

In the newly created package folder, you’ll find a Sources directory. This is where you’ll write the code for your library. You can also add a Tests folder to create unit tests for your library, ensuring it works as expected.

Open Package.swift and customize the package details. For example, specify platform requirements and dependencies if needed:

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

import PackageDescription

let package = Package(
    name: "ESNetworking",
    platforms: [
        .iOS(.v18)
    ],
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: "ESNetworking",
            targets: ["ESNetworking"]),
    ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .target(
            name: "ESNetworking"),
        .testTarget(
            name: "ESNetworkingTests",
            dependencies: ["ESNetworking"]
        ),
    ]
)

In this example:

  • platforms specifies the minimum OS versions. You can add this in case it's not already included in your Package file
  • products defines what the package will provide (in this case, a library called "ESNetworking").
  • targets are modules within your package. You have one main target for your library and another for its tests.

Step 3: Write Your Library Code

In the Sources/ESNetworking folder, add your Swift files. To keep this example small, we are going to add just a very simple class inside a NetworkingClient.swift file:

import Foundation

public class NetworkingClient {
    public func get(url: String) async -> String {
        return "Response"
    }
}

Mark classes and functions you want to be publicly available with the public access level, ensuring they’re accessible from other projects that import your package.

Step 4: Add Tests

To verify your code, add tests in the Tests/ESNetworkingTests folder. Xcode creates a test file by default, but you can add more as needed. Here’s an example of a simple test:

import Testing
@testable import ESNetworking

@Test func example() async throws {
    let sut = NetworkingClient()

    let response = await sut.get(url: "https://fakeurl.com")

    #expect(response == "Response")
}

Run the tests by selecting Product > Test in Xcode or using the ⌘U shortcut.

Step 5: Publish Your Package on GitHub

To make your package publicly available, upload it to GitHub (or the platform you prefer):

  1. Initialize a Git repository in the package’s root folder (if you haven’t already): git init.
  2. Add all files to the repository: git add ..
  3. Commit the changes: git commit -m "Initial commit".
  4. Push the repository to GitHub. First, create a new repository on GitHub, then push your code:
git remote add origin https://github.com/username/ESNetworking.git
git push -u origin main

Step 6: Adding a Version Tag

Swift packages rely on version tags for versioning. To add a version tag, use the following command:

git tag 1.0.0
git push origin 1.0.0

This creates a versioned release that others can specify when adding your package to their projects. Check what version you should choose when publishing new changes to your libraries in our Software versioning article

Step 7: Using Your Package in a Project

Once your package is on GitHub with a version tag, anyone can use it by adding it as a dependency in their Xcode project:

  1. Go to File > Add Packages.
  2. Enter the URL for your GitHub repository and specify the version (such as 1.0.0).
  3. Xcode will add your package, making it available for import in the project.

You can now import and use your library in any project with import ESNetworking.

0 Comments

Join the community to comment

Be the first to comment

Accept Cookies

We use cookies to collect and analyze information on site performance and usage, in order to provide you with better service.

Check our Privacy Policy