Multiple Apps From One Codebase, Targets in Xcode

Multiple Apps From One Codebase, Targets in Xcode

Do you have duplicate code bases for very similar applications? Does this process make it difficult to fix bugs and add innovation? Don’t worry, Xcode targets can solve this problem for you.

First, let’s look at the dictionary definition of Xcode targets; A target in Xcode can be thought of as a blueprint, or more technically, a set of configuration settings that define what you want to build. Each target can specify; product type, source files, build configurations, resources. Not clear enough? It will become clearer when we look at the example we’re about to do.

If you’ve added a watch application, a widget or a test to your application before, that means you’ve added a target before. Today, by adding an application as a target, we will manage our code for similar applications from a single codebase.


First, let’s create a product scenario; an application to be marketed to restaurants and businesses that allows waiters to receive tips through virtual payment systems, called mulTiple! I quickly created a user interface using UIKit and mock data, but let’s not forget that we can develop independently of the technology used here.

1- Let’s create a new project

2- After making the necessary configurations for using programmatic UIKit, I created classes and programmed my user interfaces.

3- Let’s write the necessary code for the interface and backend integration.

// In this section the interface code was needed, 
// but I haven't included it here because it would take up too much space 
// and distract from the main topic. If you want to check it out, 
// you can access the sample project via the GitHub link 
// at the end of the article.

import UIKit

final class ViewController: UIViewController { ...lots of code here}

4- Let’s run it! Here’s a screenshot from inside the application:

app homescreen

So far, everything has progressed as it would for a typical application. The project was automatically named “mulTiple” since I named the project as such. I will rename this target as “Customer Demo.”

We created a fantastic demo application to show potential customers, and we got a new customer! Great, our new customer, Mr. Krabs from the Krusty Krab restaurant, requested an application. However, he complained that the orange color doesn’t match the theme of his business. In addition, he would like to see his business name and employees on the application. So let’s get started!

First, let’s make some changes to our code by creating different folders for different customers.

before refactoring folders

after refactoring folders

After refactoring our folders, we can create a new target or duplicate an existing one to create our new app, Krusty Krab. I suggest duplicating from an existing one if your app needs a lot of configurations, but you can always create it from scratch.

creating a target from strach

I have duplicated the “Customer Target” and renamed it to “Krusty Krab” Also I’ve renamed its scheme name to “Krusty Krab”. Then, renamed its display name and bundle identifier as I desired. We are now ready to run and see the results.

Nice! Yes, they look the same. Let’s change it a bit. Because we duplicated from the “Customer Demo” target Xcode created an Info.plist file named Customer Demo copy-Info. Let’s rename it and move it into our new customer’s folder. Also, create an Assets file in that folder.

before and after refactoring folders

We are so close to the change. Let copy and paste assets from Customer Demo Assets to Krusty Krab Assets. This is where it gets tricky. After copying it, change the app color used in navigation bar. Under “Identity and Type” tab, uncheck or check targets you want the file to be visible/accessible.

Do you remember the file we created “CommonAssets”? You can use it to store common assets and leave it checked it's all target memberships.

changing appcolor and adjusting targets

Result

customer demo target vs. krusty krab target

Let me polish it a bit…

I’ve used xcconfig files for each customer, and separated them with targets. Defined API urls, customer IDs, app names inside these config files and updated AppIcon for Krusty Krabs.

This is how it looks with 2 different apps with one codebase

But wait, what if the customer wants to do something special?

You have some options here, The first one is to use “if checks” with your customer ID, defined in your config file. The other option is to create a new file for the view and separate it with targets. You can use the same class names with different file names, allowing you to navigate to pages with different appearances.

//
//  ViewController.swift
//  mulTiple
//
//  Created by Emirhan Karahan on 6.01.2024.
//

import UIKit

final class ViewController: UIViewController {

      override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
    }

}
//
//  SpecialViewControllerForASpecificClient.swift
//  mulTiple
//
//  Created by Emirhan Karahan on 6.01.2024.
//

import UIKit

final class ViewController: UIViewController {

      override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .green
    }

}

Another aspect to consider is the workflows. If you have two applications that require completely different workflows, this method may not be suitable for your applications.

You can access the final version of the application at github.com/emirhankarahan. Don’t forget to use the comments section for any questions you may have. Thank you!

resources

configuring-a-new-target-in-your-project

@mihail_salari/scheme-vs-target-in-xcode-unraveling-the-mystery

Images by Freepik