How to write in info.plist file while building using Swift

Posted by on February 6, 2018

Recently, I needed to write some specific configurations from one plist to the info.plist file. We have a multi-target project which should use the same values for certain configurations, I searched on multiple resources to try to find the best solution and I found two different ways of doing it, which I would present you here. One is the easy but dirty way and the other is the elegant way of doing it. So, let’s start.

Easy way – User-defined setting

The easiest way of doing this is adding a user-defined setting in your project. Then using it in the Info.plist of the targets that you want to inherit this setting.

You need to select your project and go to Build Settings

 

After that, select the plus icon next to levels, and chose Add User-Defined Setting on the drop menu.

A new setting will appear under the User-Defined section where you can choose the name you are going to use in the plists. There’s no real convention here but I prefer to use uppercase and underscores for the name, let’s define BUNDLE_DISPLAY_NAME as an example.

Then, we just go to the plist where you want to use this defined setting and set it there.

And that’s all you need. You will see your defined setting used by your target.

This solution is also good if you need to use different names, versions or settings depending on your schemes and targets. That’s the power of user-defined settings.

Elegant way – Swift script

There’s another way, the elegant way of doing it. Creating a Swift script to define these values (such as in another plist or some text file), running it as a build phase and writing directly in the info list.

Actually, you can do this using the language of your preference, but I wanted to do it with Swift since I want to practice my use of Swift outside of iOS. I will use Swift 4 to create the script.

First, you need to create the file, I prefer to keep these files outside of the project scope since it’s something that doesn’t affect the app behavior.

If you are lazy and don’t want to read all of this, here you can find the gist file with the final script.

The first thing we need to do is configure our script correctly.

The first line imports macOS SDK if you are working on an iOS or AppleWatch project. If your project is a macOS one you can ignore it. We also need to import Foundation to be able to use FileManager to read/write the list files.

We will use relativePlistFilesFolder to read your Info file, which will usually be in the root directory of your project, in that case just set it to an empty String, but in other cases (like mine) set your real path to your file.

Finally, we will define currentDirectoryPath as a constant just to make our lives easier.

I will start creating our reading plist method.

We will use the string path to read the file and return it as a dictionary. Since we don’t know what we are going to read, we need to set it to Any. We will try to read the file and return the empty dict if it doesn’t exist.

After that we will try to serialize it from a plist to a dict, we will use PropertyListSerialization class to read the file. Since the property list serialization method can throw an error we need to do it inside a do-catch block (unless you want to force the try using the exclamation mark try! ), and return an empty dictionary if it failed or the serialized data if it worked.

After this, we will create our writing method.

This one is really simple, we will cast our dictionary to an  NSDictionary so we can use the write method, and also receive the path where we want to write. Then return true or false depending on the result of the method.

The first thing I do is check if the file exists, if it doesn’t exist then something is wrong with our code and we need to check it.

After that, I just call the write method from NSDictionary with the path of the file and atomically set to false. This method would overwrite the Info.plist file and set our new dictionary with all our changes.

Finally, we can use our code to change our info list.

If you want to write/read Xcode settings, remember to use the raw value. In this case, instead of using Bundle Version we need to use CFBundleVersion if you want to see the raw values available just open your plist file on Xcode and select the option.

You can also set your custom keys here which will be written into the new file.

At the end, we just need to call our write method and return an error if something went wrong.

The last step is to add this as a build phase for every target.

To do this, we need to go to our target and select the Build Phases tab. Under it, we need to click the plus button and select New Run Script Phase.

After that, move the new run script to the first place to make sure you change the list before it’s used and set the path to find your script.

And, that’s all. Build your project and you’ll see the changes we set.

You can find the full code here.

 

I hope you found this tutorial helpful and you can use it in your future projects. If you see any error or an improvement please let me know in the comments.

Thanks and happy swifting!

Posted in: Development
Tags: , , ,

Comments

Be the first to comment.

Leave a reply

Simple Business by Nimbus Themes
Powered by WordPress