XCode Target Duplication via Code - ios

Does anyone know a tried and tested way of duplicating XCode targets programatically?
I've tried this Gist based on the xcodeproj Ruby gem but it doesn't copy all the settings (like it would do if doing it through the XCode UI)
https://gist.github.com/ratazzi/f6d9217654d6605450a0

For anyone reading I've actually taken a different approach with this.
Rather than duplicating targets and changing specific values I've utilised fastlane an in particular the 'set_info_plist' function to change values at build time that are specific to a target.
https://docs.fastlane.tools/actions/#set_info_plist_value
This is useful for things like theming changes as per the build or Free/Paid applications environments where you want one single code base that behaves differently depending on the theme or nature of the application.

Related

Is there is any way to create a IOS app as build for another app?

I have an IOS app which holds lot of Configuration settings to use the app and also this app is used in 5 warehouses, settings will be differ from one warehouse to another warehouse. So it becomes more painful for the users using this app.. Even ever they install the app then need to set the configuration settings.
So my problem is If i hardcode the settings value, it is very difficult to maintain the code for all the different warehouse. if i do small change in my app have to change in all of the 5 source code.. Even if i decide to maintain 1 code .. i have to change the setting value every time before setting the build.. It is more painful for me.
so my question is..
Is there any way to run a app and set values in configuration settings. And generate this setting app as a build ?? i don't know it will workout or not please share me some ideas..
If I understand correctly, you want to have 1 source code and there is possibility to create different Targets. Each target can have it's own configuration plist file and you can set also different preprocessor macros for each target.
How to use preprocesor macros you can see here: How can I differentiate between multiple targets in xcode at runtime
How to create targets you can see here: Add preprocessor macro to a target in xcode 6
One more possibility (besides targets) is to create a shared library and if you want to apply some configs after installation you can prompt user to download one from a server (for instance)
Yes, you can create different schemas.
For example, you can create an application for Development, Staging, Production.
You can have configurations in plist file and make it variable according to the schemas.
When your application opens it will take the values according to the schema with which it was built.
Follow this guide to create different schemas.
Also, you can integrate Fastlane to generate builds easily with different schemas with simple commands.
Yes you can have one app with different targets and schema. Then just google it there's many articles about.

Best way to Whitelabel an existing iOS App

I started working at a company which developed an App for mobile payment. There is a "Terminal"-App, which receives payments of customers and then there's the "Wallet"-App, which users can download and use to pay (at those terminals).
The project consists out of 2 targets - one for the Wallet and one for the Terminal. The App is used only in 2 Countries. It's all quite sophisticated and has a huge code base.
Now I need to whitelabel the whole product for a client, who wants to use our App (both targets) with his own branding (and maybe some additional features or without some specific features) and I'm not sure what the best way would be to achieve that.
Currently I see 3 options:
Duplicate whole project
To copy the whole project to a new folder and make my changes in that new folder would probably be the most "dirty" approach. At some point, my first code base could differ from the duplicated one too much. Additionally, if any security-related issues would come up, I would have to fix it in both projects.
Create another 2 targets
I was actually thinking that this would be the best way to go. Creating a new target for the Wallet and the Terminal and then checking the current target in the source code to decide which features should be enabled or disabled sounded pretty good to me at the beginning. But then I created the new target and noticed that I will have to set that checkmark on EVERY single class for that new target. Besides that, I'm not sure any more if that's really the best way to go.
Use If-conditions
The third option would be to wrap every function, that will be available in only one of the apps, with an if loop. I see this as the "cheapest" option because it's easy to set up and I can still maintain my code base pretty well.
Is there any other option I have? Which way would yo go?
The most significant difference between the base App and the whitelabeled one will be its language. The whitelabeled version will be right to left, but iOS does a pretty good job on that without needing me to do all the mirroring.
You definitely want the extra targets. Having a new target means it's easy to use a separate bundle identifier, signing settings and more. It might seem like a pain to have to tick a bunch of boxes to add your files to the new target (perhaps quicker to use the target's Build Phase|Compile Sources list in Xcode) but it's worth it to create a real separation between the apps.
Instead of using a bunch of source code checks to determine which white label app you're in, consider making your app more data-driven. A plist file could be used to determine which capabilities your app has, and a different plist file can be used for each target.
For example, it might contain a top-level dictionary called features, with true/false values for a bunch of feature names. You have a FeatureManager that reads the file and is the single source of truth for all app components that want to know if something should be available or not.

Why should I use a separate test target for running XCTests and how should I do that?

I once asked a question related to XCTests. And in one of the answers I was told that it is a common practice to use a separate test target (other than the main app) when running unit tests (at least, in iOS development). I tried to find some sources about it, but I couldn't
I understand, that it is probably a best practice, so I would really like to understand it. Could someone explain to me why is it important, what benefits do I get from it and how should I go about doing it? Links to some articles explaining the issue will be much appreciated.
P.S. I understand that I need special environment for tests (fake in-memory database, mocked networking layer, etc.), but up until now I managed to achieve it without a separate test host. But I believe that there might be a better way.
To answer your points:
Why is using a separate test target important?
Separation of concerns. A unit test target does not have the same kind of structure as a regular app target - it contains a test bundle, which references the app target under test, as well as the test classes and any helper classes required. It is not a duplicate of the app target with test code added to it - in fact it should not even contain the code under test. This means that you don't have to make any special effort to keep the test target in sync with the main app target - the fact that the test bundle loads the main app handles all that for you. (You made a comment on Richard Ross's answer to your previous q suggesting you've run into the difficulties duplication causes already).
How should I go about doing this? (checked on Xcode 7).
Assuming you are wanting to add a target to an existing project that doesn't have any tests, select the main project, and then click on the '+' beneath the list of targets in the project. You can also use the File->New->Target menu option.
You'll see a menu asking you to choose a template for your new target. Select 'Test' and within test select 'iOS Unit Testing Bundle'.
Check the fields in the next screen - they should be correct by default - but you might want to double check the 'Target to be Tested' field value is correct if you have a lot of targets in the project/workspace. Click 'OK' and you should have a functioning unit test bundle, with an example test that you should be able to run using Apple-U or Product->Test You'll still need to #import the app classes if you're using ObjC.
If you are creating a new project, all you need to do is tick the 'Include Unit Test' box when creating the project - no other steps are required.
Apple Docs (with links to relevant WWDC presentations)
Tutorials. Most of the tutorials around are a bit out of date. But not that much has changed, so just look at the docs and figure it out. The two below might be useful, otherwise just google. From a quick glance, most of them seem to assume that the project had unit tests set up at the beginning
http://www.raywenderlich.com/22590/beginning-automated-testing-with-xcode-part-12 (2012/iOS 6, but the process is still broadly the same. Also deals with Jenkins, Git and running tests from the CLI).
Unit testing in OSX - most recent post - not iOS, I know, but more up to date than most of the iOS tutorials (Oct 2015), and gives step by step instructions (including setting the unit test target in the build schemes, which probably won't be necessary in your case). Probably worth a look anyway.

Create similar iOS apps reusing almost everything (with Xcode)

I want to make multiple apps which share the same structure and code, but have different images, fonts, names and urls.
I would like a simple way to make this apps without replicating the whole project, so that when I find a bug I'll have to correct it only once.
Thank you.
PS: It isn't important the language (Objective-C or Swift)
Create multiple targets within the same project. You can then include or exclude asset catalogues, configuration JSON files etc. on a per-target basis. If you're consistent with the names this should get you most of the way there. You can also look at target-specific build flags or constants.

How to reuse an Xcode project into a new project? Static library, Framework, Targets?

I built an iOS project (actually workspace because of Pods) that is 100% functional, with its logic and UI (Storyboard and xibs). Now I would like to reuse this app/project as a "core" for future apps.
I've been searching about it and there are several solutions like Static libraries, Frameworks and Targets. But I am not sure which one would be the best in my case. I would like to reuse all the UI part as well.
I saw that most of the people agree that the best approach for reusing code is static libraries, even thought it looks not so straight forward. But I think for reusing UI probably Targets is the best solution. The problem I see is that if a build 10 apps based on my core project, the new project will be huge, so probably it is not the best option.
I don't know if you guys have any better idea or opinion.
Thanks in advance!!
There are several things you can do, and I will try to go through them.
If you have minor changes on your "base" app, then the best thing would be using targets(build schemes). This way you can add things to build phases and therefore, add files that you need. This might be the quickest possible way to do what you want but here are some drawbacks: What if you have 5 apps, and for each one you have QA and prod. That 10 build phases. If you keep using your app in no time you will find hard to manage it.
Another thing could be to create different project, and include all the files you have (and you need), inherit from there and have extended functionality/UI/UX. This is slower approach then number 1, but you will have dependency on the files that you might change in one app and don't want to propagate that change in other apps. So the drawback would be that you have to be extra careful, and plan a lot of things in advance.
Third thing could be to create base app group(or project) and then you are certain what to do, where and what that change could do to other apps(since you know that this file is actually being reused).
And finally, there is a framework, which is my favorite. I am working on one project that inherits base app and we found that is a huge problem. You start separated and then, one thing by one, you have entangled code for specific app and base app like headphones in pocket. And if you don't refactor it ASAP, it will became really hard to resolve these kind of issue. Not to mention merging and other stuff. Here is an excellent article about creating framework http://www.raywenderlich.com/65964/create-a-framework-for-ios . Off course, there is a price to pay and that's every change that you create you must update library and add it again to project. This thing can be easily forgotten and if you are working in team could produce build crash.
All after all, you predicate that you will have more then 5 apps, so I would say go with the framework. This way you will have much cleaner and separated app, and won't have to think about changing things and how these changes would affect your other apps.
I recommend you use a custom project template. I did it perfectly today. I had the same needs as your. Follow this link: https://github.com/reidmain/Xcode-6-Project-Templates/tree/master/iOS%20Application.xctemplate
Download it. You can add all the files from existing project into this template, storyboards too. If you have any doubts I will help you.

Resources