Managing App, Frameworks, and Swift Packages with Xcode Workspace

Photo by Carissa Gan on Unsplash
Photo by Carissa Gan on Unsplash
After having modularized a project, the project is divided into an app project or a framework project, and several Swift packages. We can easily manage these sub-projects with Xcode workspaces.

After having modularized a project, the project is divided into an app project or a framework project, and several Swift packages. We can easily manage these sub-projects with Xcode workspaces. This article will introduce how to use Xcode Workspaces to manage several sub-projects.

The complete code for this chapter can be found in .

Creating a Xcode Workspace

Click File -> New -> Workspace to create a workspace.

File -> New -> Workspace
File -> New -> Workspace

Enter Greeting as the name of the workspace. Create a folder called iOSWorkspaceExample, and create the Greeting workspace under this folder.

Create Greeting workspace.
Create Greeting workspace.

The Greeting workspace is created. But currently it doesn’t contain any projects.

Created workspace contains no projects.
Created workspace contains no projects.

Creating a Swift Package in Workspace

Now we are going to create a Swift package in the Greeting workspace. Click File -> New -> Package.

File -> New -> Package.
File -> New -> Package.

Enter GreetingPhrases as the name of the Swift package and choose to create it under the iOSWorkspaceExample folder. In the Add to and Group fields at the bottom of the dialog, we choose to add GreetingPhrases to the Greeting workspace and to the Greeting group.

Create GreetingPhrases Swift package.
Create GreetingPhrases Swift package.

The Greeting workspace now includes a Swift package.

Workspace contains Greeting package.
Workspace contains Greeting package.

Creating a Framework Project in Workspace

Next we will create a framework in the Greeting workspace. Click File -> New -> Project.

File -> New -> Project.
File -> New -> Project.

Choose to create a Framework project.

Choose framework to create.
Choose framework to create.

Enter GreetingUI as the name of the framework.

Enter GreetingUI as the name of the framework.
Enter GreetingUI as the name of the framework.

Choose to create GreetingUI under the folder iOSWorkspaceExample. In the Add to and Group fields at the bottom of the dialog, we choose to add GreetingUI to the Greeting workspace and to the Greeting group.

Create GreetingUI framework.
Create GreetingUI framework.

The Greeting workspace now contains a Swift package and a framework.

Greeting workspace contains GreetingPhrases package and GreetingUI framework.
Greeting workspace contains GreetingPhrases package and GreetingUI framework.

Creating an App Project in Workspace

Finally, we will create an App in the Greeting workspace. Click File -> New -> Project.

File -> New -> Project.
File -> New -> Project.

Choose Create an App Project.

Choose App to create.
Choose App to create.

Enter GreetingApp as the name of the App.

Enter GreetingApp as the name of the app.
Enter GreetingApp as the name of the app.

Choose to create GreetingApp under the folder iOSWorkspaceExample. In the Add to and Group fields at the bottom of the dialog, we choose to add GreetingApp to the Greeting workspace and to the Greeting group.

Create GreetingApp.
Create GreetingApp.

Now the Greeting workspace contains an app, a framework, and a Swift package.

Greeting workspace contains GreetingPhrases, GreetingUI, and GreetingApp.
Greeting workspace contains GreetingPhrases, GreetingUI, and GreetingApp.

Add Swift Package Dependency to Framework

Both GreetingUI and GreetingPhrases are inside the Greeting workspace. So GreetingUI does not need to add GreetingPhrases dependency. Xcode workspace will automatically help us handle the dependencies between all projects in the workspace. But GreetingUI doesn’t yet work with GreetingPhrases. It must add GreetingPhrases to its Frameworks and Libraries list. And this step must be done by us, Xcode will not handle it for us.

Select the GreetingUI target under TARGETS of GreetingUI, and click the + button under Frameworks and Libraries.

GreetingUI -> TARGETS -> GreetingPhrases.
GreetingUI -> TARGETS -> GreetingPhrases.

Choose to add the GreetingPhrases library.

Choose GreetingPhrases library to add to GreetingUI.
Choose GreetingPhrases library to add to GreetingUI.

After adding the GreetingPhrases library to the Frameworks and Libraries list of GreetingUI, GreetingUI can use GreetingPhrases.

GreetingUI has GreetingPhrases in the Frameworks and libraries list.
GreetingUI has GreetingPhrases in the Frameworks and libraries list.

The following code shows how to use GreetingPhrase in GreetingUI.

import UIKit
import GreetingPhrases

public class GreetingViewController: UIViewController {
    public static func newInstance() -> GreetingViewController {
        let storyboard = UIStoryboard(name: "Greeting", bundle: Bundle(for: Self.self))
        let viewController = storyboard.instantiateViewController(withIdentifier: "GreetingViewController") as! GreetingViewController
        return viewController
    }
    
    @IBOutlet weak var greetingLabel: UILabel!
    
    public override func viewDidLoad() {
        super.viewDidLoad()

        greetingLabel.text = GreetingPhrases().text
    }
}

Add Swift Package and Framework dependencies to App

GreetingApp does not need to add the GreetingPhrases dependency, because the Xcode workspace will automatically handle it for us. But GreetingApp must add GreetingPhrases and GreetingUI to its Frameworks and Libraries list.

Select the GreetingApp target under TARGETS of GreetingApp, and click the + button under Frameworks and Libraries.

GreetingApp -> TARGETS -> GreetingApp.
GreetingApp -> TARGETS -> GreetingApp.

Choose to add the GreetingPhrases library.

Choose GreetingPhrases library to add to GreetingApp.
Choose GreetingPhrases library to add to GreetingApp.

Click the + button again and choose to add the GreetingUI framework.

Choose GreetingUI framework to add to GreetingApp.
Choose GreetingUI framework to add to GreetingApp.

After adding the GreetingPhrases library and the GreetingUI framework to the GreetingApp’s Frameworks and Libraries list, the GreetingApp can use them.

GreetingApp has GreetingPhrases and GreetingUI in the Frameworks and libraries list.
GreetingApp has GreetingPhrases and GreetingUI in the Frameworks and libraries list.

The following code shows how to use GreetingPhrase and GreetingUI in GreetingApp.

import UIKit
import GreetingUI
import GreetingPhrases

class ViewController: UIViewController {
    @IBOutlet weak var showButton: UIButton!
    
    @IBAction func onClick(_ sender: Any) {
        let viewController = GreetingViewController.newInstance()
        present(viewController, animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        showButton.setTitle("Show \(GreetingPhrases().text)", for: .normal)
    }
}

Executing App

Because Greeting workspace has three schemes, remember to choose GreetingApp to execute. Even if we modify the code in GreetingUI or GreetingPhrases, we can directly execute GreetingApp, instead of switching to GreetingUI or GreetingPhrases to compile first, and then switch back to GreetingApp to execute. When we execute GreetingApp, Xcode will automatically recompile GreetingUI and GreetingPhrases for us. Isn’t it very convenient!

Choose GreetingApp scheme to run.
Choose GreetingApp scheme to run.

Conclusion

Swift packages allow us to modularize a project by splitting it into several Swift packages. Or when we are developing a framework, we need an app to test it. In other words, when our project has several sub-projects, Xcode workspace can help me effectively manage the dependencies between them.

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like
Photo by Alex Alvarez on Unsplash
Read More

Dispatch Queue Tutorial

Grand Central Dispatch (GCD) provides efficient concurrent processing so that we don’t need to directly manage multiple threads. Its dispatch queues can execute tasks serially or concurrently.
Read More