Sub-modules for Xcode

Ralph Bergmann
Karlmax Berlin
Published in
4 min readFeb 1, 2021

I’ve been developing software for around 20 years — sometimes for myself, but mostly for clients. For me, it’s much more than a job: it’s fun to solve a problem with elegant and beautiful code. And, of course, you sleep so much better when it’s also maintainable, testable, and reusable — all those fancy buzzwords!

However, over any project's lifespan, the development team usually changes. Your client might ask for new features, while libraries are often updated or become deprecated. To carry out these maintenance tasks, a good project architecture is vital. Otherwise, you spend too much time troubleshooting tasks. When the budget runs out, both you and your boss will be frustrated — your client, too, when you don’t make the deadline.

As a good developer, you will be familiar with Uncle Bob’s Clean Architecture. In short, this architecture involves splitting your code into modules.

For Android developers, splitting the project into sub-modules is such a simple task — just ask Android Studio (or IntelliJ IDEA, I’m not sure if other IDEs also have such a feature) to create a sub-module.

But how do you split an Xcode project into modules? Well, that’s exactly what I’m going to show you here.

Let’s start

Open Xcode and create a new, empty workspace. You can’t do this from the Xcode Welcome screen, but you can use the ⌃ ⌘ N (control + command + n) shortcut. Create a new empty folder and call it modules. You can choose a different name, but for this article, I will use modules.

Add a new project to this workspace with ⇧ ⌘ N (shift + command + n). In the opening dialog, select the iOS App template and call it main.

Make sure you create it in the modules folder and also choose to add it to the app workspace and app group.

Add another new project, but now select the iOS Framework template and call it core. Create this in the modules folder too and also add it to the app workspace and app group.

Your folder structure should now look like this:

Link it together

It’s now time to link the core project/module into the main project.

Select the main target of the main project and drag and drop the core.framework into the Frameworks, Libraries, and Embedded Content section.

A simple test

To test it, create a new Swift File (⌘ N) in the core project with this simple method:

import Foundation

public func name() -> String {
return "Ralph"
}
@ralph-bergmann

In the main project, change the ContentView.swift. Add the import core statement and call the name() method:

import SwiftUI
import core

struct ContentView: View {
var body: some View {
Text("Hello, \(name())!").padding()
}
}

Xcode may display an error regarding the minimum deployment target. To fix this, change it to 13.0 in both main and core projects.

Add dependencies

Right now, I’m using CocoaPods for dependency management because I’m not so familiar with Swift Packages.

In the modules folder, create a Podfile file with this content and call pod install.

workspace 'app.xcworkspace'
platform :ios, '13.0'
use_frameworks!

def core_pods
pod 'SwiftDate', '~> 6.3.1'
end

def main_pods
# add pods for the main target here
end

target 'core' do
project 'core/core.xcodeproj'

core_pods
end

target 'main' do
project 'main/main.xcodeproj'

core_pods
main_pods
end

The pod install command initializes CocoaPods for this workspace (because we haven’t done that so far) and adds the SwiftDate pod as a dependency on the core project.

We can now use SwiftDate (I only use this to show how to add a dependency). Change the ContentView.swift and Name.swift file in the core project as follows:

import SwiftUI
import core

struct ContentView: View {
var body: some View {
Text("Today in one year is: \(nextYear())").padding()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import Foundation
import SwiftDate


public func nextYear() -> String {
let nextYear = (Date() + 1.years)
return nextYear.weekdayName(.default)
}

Done

You can find the complete project at:

--

--