3

I have this needs.

I developed an app and I want to duplicate it. I can copy and paste the project but if I do this 10 times can be a problem. The problem is, if I found a bug in the 10th duplicate, I have to review all other projects and I don't want to do this.

There is a clean way to solve this problem?

In other words, I have only one big code. The differences between the apps that I have to deploy are:

  • Launcher icon
  • Domain of the HTTP request
  • Package name
  • Splash Screen
  • App name
  • Some integers inside the app
  • Some assets

In Android, I do this with gradle, in particular, with the flavors. How I can do the same with Swift?

linosorice
  • 166
  • 1
  • 12

3 Answers3

4

Create a single project with multiple targets. Each target would have a different info.plist and whatever other changes you need, but shared source.

Edit:

There is an open source tool called xcodegen that lets you define your projects using yaml (.yml) files. You then run the xcodegen script and it creates project files that contain all your different targets and your dependencies. That might be a cleaner way to build your multiple targets that contain the same source and build rules but different assets.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • How can I create multiple target with the same source? – linosorice Dec 18 '16 at 13:14
  • In your project, select the file menu, new, new target. In the resulting dialog, select the desired type of application. Once you've added a new target you can select your source files and other resources and then display the "identity inspector". In the identity inspector there is a section "target membership". Check the checkbox for your new target(s) in order to add the selected file to your target(s). – Duncan C Dec 18 '16 at 15:10
  • Note that Apple will likely reject multiple apps that have just been "re-skinned" with different art. They have language in their app store submission guidelines that specifically say you should not submit apps that are just a re-skinning of an existing app store app. – Duncan C Dec 18 '16 at 15:11
  • My apps have different contents with the same skin e some different colors. Do you think that this is a problem? – linosorice Dec 18 '16 at 15:16
  • With your solution, every time I add a new target to the project, do I have to select all file and check the checkbox of the target? – linosorice Dec 19 '16 at 01:35
  • 1
    Normally, yes. You could probably edit the project files and do it all at once though. – Duncan C Dec 19 '16 at 01:44
  • @DuncanC how to add all files at once to the new Target ? – JAHelia May 11 '23 at 10:47
  • This is an old thread. See my edit suggesting using the xcodegen tool. – Duncan C May 11 '23 at 16:49
0

I would do this with Git:

In your origin repository, prepare your project with placeholders:

  • Try to make a file where you define constants for the domain, the integers you mentioned etc. That file you could call Constants.swift.

  • Put all assets you need to change in one .xcassets. (a different one than the assets that will stay the same) For example the Icon. You can already add the image-sets you want to have in your apps, but leave them empty (or alternatively add placeholder images)

  • Write a placeholder for the app name and package name

  • create a default splash screen (I guess you mean the launch screen). This could either be empty or if you want it to be similar in all apps, prepare it a bit so you don't have to change much for each app

When you have committed and pushed your main project, create forks for each of your apps. In the forks, you can change everything that you have prepared as placeholder.

If there is a but somewhere, fix it in the origin. Then you can merge the changes easily to each of your forks.

FelixSFD
  • 6,052
  • 10
  • 43
  • 117
0

Here's my setup:

(1) Create a new project of type Framework.

Move all shared code - extensions, subclasses, image assets, even .xib files - into a this project. I created an App/Bundle ID ("com.company.framework") but I'm not sure if it is necessary for App Store submission. Also, checking off the "Allow app extension API only" will remove the warning you'll get.

For files like images or text files, create bundles and drag the bundles into the framework. I've found you can add new images/files through Xcode. To retrieve them, here's the code:

public func returnKernel(_ named:String) -> String {
    let myBundle = Bundle.init(identifier: "com.company.framework")
    let kernelPath = (myBundle?.path(forResource: "cikernels", ofType: "bundle"))! + "/" + named + ".cikernel"
    do {
        return try String(contentsOfFile: kernelPath)
    }
    catch let error as NSError {
        return error.description
    }
}

(2) Create a second project, this time for your specific app.

Let's say you called your framework "Kernel". All public declared code is available by adding:

import Kernel

Now, here's the best part (for me): you have two ways to work with this setup.

(3a) Drag your framework .xcodeproj into your app project.

PROS: You can (a) make changes to your framework source code and (b) build both at once.

CON: You can only have one app project open at once because Xcode detects that the framework project is open.

(3b) Drag the Kernel.framework project into your app project.

PRO: You can have all your apps open at once.

CONS: You will need to (a) make your framework source changes in it's project, and - I think - (b) manually update every app with the rebuilt framework.

I say "I think" because I use the former set up. It's a small price to pay to have one app open at a time. Typically if you are making a framework change it's for a single app.

FINAL NOTES:

  • Changes made to the framework while working in "app #1" will be picked up when you open "app #2".

  • I have separate Git repositories for (a) each app and (b) my framework, both locally and on GitHub. Works perfectly.

  • I have separate Bundle/App IDs (and versions) set up for (a) each app and (b) my framework in the Developer Portal.

  • Come App Store submission time, I archive the app and upload it. The framework comes along for the ride.