Using Cordova CLI on Mac OS X to build iOS apps – updated 3/2018

This article gets you up to speed on how to integrate your HTML/CSS/JS app with Cordova into an iOS app using a Mac and prepare it for App Store submission. This article assumes you’ve already followed the steps on to:

Download Node.js
Add PATH statements to .profile

In this article, I am referencing Mac OS X Yosemite 10.10.5 and Xcode 6.3.1 on a Mac Mini. Cordova CLI 5.4.1 was installed. I am referencing “cordova” in the command-line interface, not “phonegap.” This project will not use the PhoneGap Build service. Any updates to these programs may affect the following instructions.

Download Apple’s latest OS  and Xcode if you haven’t already: 

Before you can install the app you create with Cordova on your device, you need to sign up as a Developer with Apple and go through the business documentation, Certificate Signing, Developer Certificate process, and more, all of which are detailed on Apple’s web site (, under Prepare for App Submission. Nevertheless, you can skip all those steps and still see your work in the the iOS Simulator included with Xcode — you just won’t be able to view the app in your device or App Store. Xcode is a free download you can download now, but the Developer status comes at $99 a year and is needed if you want to submit apps to the app store or test on your device.

If you are new to creating apps for the App Store, you’ll want to peruse the App Store Review and other Guidelines to make sure your app meets the rules: You are strongly encouraged to make use of these documents before you start your project, lest you run afoul of Apple’s rules for what apps they will and will not allow in the App Store.

Cordova uses the command-line interface (CLI) to generate the files needed to start the project.  This article covers the creation of an app from CLI creation to upload binary to Apple.

Install Cordova CLI

1. With Node.js installed, open the Terminal app by clicking on it in the dock at bottom and issue the following command:

sudo npm install -g cordova

Or update your installation with this article:

2. Give the root password and hit Enter. I got a series of ERR lines, ending with:

npm ERR! not ok code 0

I kept pasting the command and hitting Enter over and over until it completed (maybe three times). When successful, you should get a long list of lines beginning with “npm http,” then finally ending with a series of words containing the @ symbol and digit/dot pairings, terminating with your username at the end.

Create Cordova Project Files with CLI

1. Open a Finder window and select the folder you want to create your project’s folder inside of, such as /CordovaApps
2. Open the Terminal app (click on its icon in the dock below, or click on the magnifying glass at top right and type in “terminal”), type cd and a space (for “change directory”), drag the selected folder to the Terminal screen, let go, click on the Terminal to select it, then hit Return. This will orient all commands to that folder.

For this project, all of your commands will always begin with “cordova.”

3. Type the following in the terminal (“myApp” is this project’s app name — make your final app name less than 50 characters):

cordova create myApp

Basic files are generated in the /CordovaApps/myApp folder.

4. Enter the new folder you created in Terminal with the cd (change directory) command:

cd myApp

5. CLI only downloaded the skeleton files needed for all platforms. Now you need to download the specific files for iOS:

cordova platform add ios

6. Open the /myApp/platforms folder to see a new folder, /ios.

7. Cordova included several files for a default one-screen app, complete with splashscreen and icon. To build the default Cordova app, type:

cordova build ios

8. After a time, the Xcode file was built and saved as: myApp/platforms/ios/HelloWorld.xcodeproj. Double-click on this file to open it in Xcode.

If you’re unfamiliar with the Xcode environment, read this paragraph. Otherwise, skip to the next one. When the Xcode screen comes on, look at the top and see a progress bar showing you the progress of the Open process. You’ll see a familiar Play triangle near the top left, a square Stop button, and to the right, the app name > iPhone 6s Plus (which is the clickable name of the simulator or device — if you click on it you’ll get a list of devices to choose from). Below that at left is a string of small icons. You should click on all of them to get an idea of what information they hold. (Don’t worry — you won’t break anything doing so!) The far left icon is a file folder icon; click on it to see the app directory. If the app files are not showing, there is a drop-down triangle to the left of an icon that represents your Xcode app. You can click on the small triangle to view the project contents.

9. Click on the solid Play triangle to view the project in the device simulator. The progress indicator at top keeps you apprised of the status. If you see a warning symbol with a number at right, it indicates potential problems. In that case, you may want to review this page to see if you missed something:

An iPhone screen appears, showing a white Apple logo on a black screen. If it is too large to fit in your screen, click on Window > Scale and an appropriate number, like 33%.  Below it is the progress bar. When it turns all white, you see the home screen. If the app does not launch automatically, then swipe the screen with your mouse until you see you app’s icon, then click on it.

If this is the default Cordova app, you’ll see a logo above the words APACHE CORDOVA with “Device is Ready” pulsing. This shows that the project is successfully showing the default index.html screen. Or if you had already replaced the default Cordova page with your own, your page would be seen.

10. Experiment. Try this with the iPhone simulator:
a) Click on the simulator then on Hardware > Device and choose among the available devices (they did not all work when I tried it).
b) Click on Window > Scale and resize the simulator (important if the entire simulator doesn’t fit in your window).
c) With Edit > Copy Screen you can grab it and possibly save for uploading as screenshots, if your screen and simulator sizes are large enough.
d) Click on Debug > Open System Log… to view the console output in separate windows. I personally did not find this information helpful.

11. In Xcode, click on the square Stop icon. The Simulator screen reverts to the device home screen with its icons. Click and hold on the app icon until it quivers, and an X appears. Confirm, then Hardware > Home. I recommend you delete the icon before creating a new build lest errors pile up. Sometimes the old code is not fully overwritten with a new cordova build process.

12. When you make changes to the app and open it in Xcode, you’ll want to make sure to click on your app name in the left column, then check in the middle pane under Deployment Info > Device Orientation that all relevant orientations have been checked. Also make sure that Devices shows iPhone, iPad, or Universal (for both device types).

There were many warnings in Xcode for CordovaLibs regarding stuff being deprecated. Response: simply double-click on “Update to recommended…” then on Perform Changes. Ignore all other warnings.

Application Transport Security

The Whitelist Plugin has been deprecated for platform ios 3.9.2. We don’t include the Cordova whitelist plugin for iOS9.

However, Apple is incorporating strict security protocols for iOS9 and beyond with their new Application Transport Security. They require that our app’s external connections go only to servers incorporating HTTPS and other security measures. If your app already connects only to URLs that begin with HTTPS, you are probably good to go (though there is more to it than that — see the resource link following).

But what if your connections go to HTTP and not HTTPS? What if you don’t have access to the HTTP servers to upgrade them to HTTPS? Then you’ll need to opt out of ATS by allowing all connections (or all connections with some exceptions; see the resource below).

In Xcode, open /Resources/xxx-info.plist. Click on the arrow for App Transport Security  Settings. You’ll see that Allow Arbitrary Loads has been set to YES, which means your app is inherently insecure; it will allow all connections, including HTTP. I believe this was set because in our config.xml we have the line <access origin=“*” />, which allows all connections. (The info.plist is populated by the information in config.xml.)


Add the InAppBrowser Plugin

Add to the config.xml file


1. Open the myApp/www/config.xml file in a text editor (I use TextWrangler).

The config.xml page is one of the reasons CLI (command line interface) is so good. We add our platform-related information to that page rather than opening up page after page in the different platform SDKs. The SDKs use the information in config.xml to prepare its own platform version.

2. While we’re on that page, change the other sections:

a. Change the version=”0.0.1″ to the correct version, like version=”1.0.0.″ When you fill out the fields for the app in the Apple dev site, you’ll put this in the version field, not “1.0,” or the app will not pass validation.
b. Change the <description> line.
c. Change the <author> section.
d. Make sure the “widget id” is the name of your app in reverse domain style, like com.developername.myApp. It needs to match up with the wording you put in the Apple dev site — the case must match or it will not pass validation.
e. Change the <name> to be what you want under the icon on the device’s home screen. 11 characters or fewer, because the name won’t wrap if it’s too long. This will also change the .xcodeproj filename. Spaces are permitted.


Issue found when creating this article

At first, the default project was called HelloCordova by Cordova in the config.xml <name></name> section, which I overwrote as myApp.

Problem encountered: What happened in Xcode is that all those names are being remembered in the Xcode scheme – all except the current myApp. The HelloCordova and My App both default to Mac OS X in the scheme, and the only other selectable scheme is CordovaLib.

If you changed the <name> section and experience this problem, just remove the iOS platform with cordova platform rm ios in Terminal and add it back again with cordova platform add ios . That removed all the old data and started afresh. Note that this command will also remove all icons and splashscreen files too, and you’ll need to drag them back into Xcode the next time you do a cordova prepare ios or cordova build ios.

3. Make sure all pages using a Cordova API reference has the following in the < head> above all other .js references, and references cordova.js as being in the root folder. It needs to be on every page that uses a Cordova plugin. The lack of this part is one of the reasons why plugins fail:

 document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {

Cordova.js will be automatically added to the /www folder whenever you do a cordova prepare or cordova build. Make sure your pages access that folder for cordova.js.

The entire top part of the page in my case is:

<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no" name="viewport">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: 'unsafe-eval'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *">
App Name

< script type="text/javascript" charset="utf-8" src="cordova.js"></script> 
< script>
// Wait for Cordova to load
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is ready
function onDeviceReady() {

(WordPress isn’t retaining the formatted script tags in the document that contain opening and closing angle brackets, but I was able to include them by inserting a space after an opening bracket like this: < script. If you copy/paste the above, make sure you remove that space from two locations above.)

Note the reference to cordova.js. This line must point to the www/ folder. If the page is in www/chapters/here.html, then you would add ../ for each folder away from www/; so in this case the line would read:

< script type="text/javascript" charset="utf-8" src="../cordova.js"></script>

If you have questions about the <meta http-equiv=”Content-Security-Policy” lines, please read these pages:

4. Now let’s test it. Open Cordova’s /myApp/www/index.html page and replace portions with the following lines in these inAppBrowser instructions:

5. Save the page. Whenever you make a change to a project’s files, you must do the following steps before opening the project in Xcode. In Terminal:

cordova prepare ios

6. Double-click on the/myApp/platforms/ios/myApp.xcodeproj file to open it in Xcode, then Project > Clean. That purges the old files and makes sure you have the current build. Then you Build and Run in the sim of your choice. When you are finished and want to make more changes, delete the icon from the Simulator to make sure all traces are gone: Press and hold on the icon until the X appears in one corner. Click on the X. Affirm deletion. Click on Home button.

Add the Dialogs Plugin (optional)


I don’t like the default JavaScript alerts. The title of the alert gives the filename of the page, like index.html, rather than something nicer (or left empty). The Dialogs plugin gives us a few more options to customize the alert. See the resource above for more options than the sample I’m giving below.

1. Still in your project’s folder in Terminal, type the add command for the plugin:

cordova plugin add cordova-plugin-dialogs --save

2. These dialogs can’t appear until after the DeviceReady event, so make sure that section appears at the top of the page if yours is a multi-page app:

< script type="text/javascript" src="cordova.js"></script>
 < script>
 // Wait for device API libraries to load 
 document.addEventListener("deviceready", onDeviceReady, false); 
 // device APIs are available 
 function onDeviceReady() { 


3. Enter the following alert code above the </head> line. The function confirmation() is the code for the alert that the button will pop up; function alertDismissed() is the code that will execute when the user taps the Done button in the alert:

function alertDismissed() {
 // do something, like redirect to an external page, or do nothing'', '_blank');
function confirmation() {
 'Here is the alert!', // message
 alertDismissed, // callback (execute the above function of this name)
 'Your Title Here', // title
 'Done' // text of the close button

4. Add a button to execute the above confirmation() function. You can put this after the <body> line:

<button onclick="confirmation(); return false;" style="padding:1em; margin=1em; background-color:#ddd;">Pop the alert</button>

If you want more than one notification dialog on a page, then copy the above over and over for each dialog, but give each one different function and callback names to keep them unique for each one.

I changed this standard alert:

alert('Setup sheet removed from list.');

… to the new style:

 'Setup sheet removed from list'

I updated this:

var clearSets = function()
{ var answer = confirm("You are about to erase the data for this setup. Action cannot be undone. Are you sure?");
 if (answer) {
 else {

… to this:

var clearSets = function()
{ var answer = navigator.notification.confirm(
 'You are about to erase the data for this setup. Action cannot be undone. Are you sure?', // message
 removeSet, // callback
 'Confirm', // title
 'Yes' // buttonName

Add FastClick.js

What does FastClick do? When you tap on a button or link, the system waits 300ms to see if you will tap again (a double-tap). If you don’t tap again within that 300ms period, then it assumes a single-tap and executes. FastClick removes this 300ms delay so your taps execute right away. All my buttons need single-tap only, so this is ideal. Without FastClick.js, you should use “touchstart” and “touchend” for your links instead of “onclick.” See:


1. To integrate FastClick.js, Go to the resource page above, click on the Download button and save it to the hard drive.

2. Uncompress the zip file and copy fastclick.js (in the /lib folder) to /myApp/www/js.

3. In all your pages where the file needs to be used, add above the </head> line:

< script type="application/javascript" src="js/fastclick.js"></script>

(Note that I deliberately added a space after “<” lest this WordPress page convert it to code. Remove this space for your project.)

4. In all your pages where the file needs to be used, add after the onDeviceReady script:

< script>
if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
    }, false);

If onDeviceReady() is not used on the page, enclose the above in tags and put it above the </head> tag. Now all your taps should result in a faster response time.

5. Sometimes you’ll need FastClick to ignore certain elements. You can do this easily by adding the needsclick class:

< a class="needsclick">Ignored by FastClick</a>

Please read the section below about the /Merges folder if you are creating this app for multiple platforms.

Add Your Icons


1. Use the free online service at to generate your icons. The steps that follow assume you are using this service. Create a 512×512 icon and upload it to the service. When it is finished, enter your email to get the results as an attachment to an email.

If you are not using the above service, then skip steps 3-5 to create and install the icons by hand: You’ll install these icons in /myApp/res/ios/ so they match the folders referenced in config.xml.

2. Create a new folder, /myApp/res/icon/ios/

3. Download the zipped file from the email and uncompress it. You should find the folder, AppIcon.appiconset. It includes the icons and a json file.

4. Place that folder inside the folder we created in step 2. We place them there in case we need to remove and re-add the /platforms/ios folder in the future (which would delete the icons files). So this is just a safe place for the icons.

5. Copy the just-downloaded /myApp/res/icon/ios/AppIcon.appiconset to /myApp/platforms/ios/mypp/images.xcassets/ to completely overwrite the existing AppIcon.appiconset. Xcode will automatically discover these files and use them. So we do not need to add anything to config.xml as we did in the past.

6. We need to see if the assets work in Xcode. In Terminal:

cordova prepare ios

7. Double-click on the /myApp/platforms/ios/myApp.xcodeproj file to open it in Xcode.

8. In Xcode: Product > Clean. If it is grayed out, then go to Product > New scheme… and call your new scheme myApp. Then it will show up in the scheme section. Now you can Product > Clean.

9. Verify whether your icons are recognized. Click on your folder icon at upper left, then on myApp, if the myApp file structure is not already showing. Click on /Resources, then on /images.xcassets, then on AppIcon. The pane should now be filled with your icons in the appropriate icon wells.

I found extra, unassigned icons at the bottom. Click then right-click on each to remove them. Mine were (filenames shortened): icon-App-4…40@1x.png, icon-App-6…60@1x.png, icon-App-7…76@1x.png, icon-App-7…76@3x.png.

You’ll notice that the 1024 x 1024 iTunesArtwork.png file is missing. In the past, we would upload that in iTunes Connect online. So merely drag the file into that empty well, and Xcode will accept it. When we close Xcode and look at the Contents.json file in /platforms/ios/myApp.xcodeproj/Images.xcassets/AppIcon.appiconset, we see these lines added:

 "idiom": "ios-marketing",

Go ahead and copy Content.json to your backup myApp/res/… subfolder along with the iTunesArtwork file. Now you shouldn’t have to drag the file each time.

Add Your Launch Images (Splash Screens)


1. The splash screen (“launch screen” by Apple) is the image loaded before the app’s home screen appears. We add splash screen functionality with a plugin. In Terminal, making sure it starts within your myApp folder, add the plugin with:

cordova plugin add cordova-plugin-splashscreen --save

(To remove a plugin, type cordova plugin list and view the list of available plugins, then type cordova plugin rm and copy/paste the plugin line at the end ( like cordova plugin rm cordova-plugin-splashscreen), then hit Enter.)

2. Create new subfolders (“res” = resources): /myApp/res/screen/ios

3. Copy /platforms/ios/myApp/Images.xcassets/LaunchImage.launchimage to the folder we made in step 2. This is to keep it safe in case we need to remove the iOS platform — that step would also delete all of our screens as well.

4. Create all your screens of exactly the same size and filenames as in/myApp/res/screen/ios/LaunchImage.launchimage, then overwrite the files there. Keep the Contents.json file intact.

5. Copy that /LaunchImage.launchimage folder over the one in /Images.xcassets to replace the default Cordova screens with your own.

Here is a process to make the splash screens by hand with Photoshop.

Create a 1200px square image and fill it with your launch screen content. Save as ios-screens-prelim.psd.

Create a 2208px square image, and place ios-screens-prelim.psd in center. Save as ios-screens-template.psd.

Landscape images:
1. Narrow the canvas size height to 1242px height. Save as Default-Landscape-736h.png (2208 x 1242).

2a. Reduce image #1 (not crop) to 2048px width.
2b. Widen canvas size to 1536px height. Save as Default-Landscape@2x~ipad.png (2048 x 1536).

3a. Reduce image size of #2b to 1024px width. Save as Default-Landscape~ipad.png (1024 x 768).
3b. Close image without saving to preserve original 2208px size.

Portrait images:
Open ios-screens.template.psd

4. Make canvas size of 1242px width, effectively cropping the image width. Save as Default-736h.png (1242 x 2208).

5a. Reduce image of #4 (not crop) to 750px width.
5b. Make canvas size height of 1334px if it is not already. Save as Default-667h.png (750 x 1334).

6a. Reduce image of #5b (not crop) to 640px width.
6b. Make canvas size height of 1136px if it is not already. Save as Default-568h@2x~iphone.png (640 x 1136).

7. Make canvas size height of #6b to 960px, effectively cropping the image. Save as Default@2x~iphone.png (640 x 960).

8a. Reduce image of #7 (not crop) to 320px width. Save as Default~iphone.png (320 x 480).
8b. Close image without saving to preserve original 2208px size.

Open ios-screens.template.psd

9a. Make canvas size width of 1536px, effectively cropping the image.
9b. Make canvas size height of 2048px. Save as Default-Portrait@2x~ipad.png (1536 x 2048).

10. Reduce image of #9b (not crop) to 768px width. Save as Default-Portrait~ipad.png (768 x 1024).

Final Steps

1. Open your index.html page and change the document.addEventListener(“deviceready”, onDeviceReady, false); section so it reads like the following to turn off your splash screen when DeviceReady has fired:

// Wait for device API libraries to load 
document.addEventListener("deviceready", onDeviceReady, false); 
// device APIs are available

function onDeviceReady() {

2. Put these files into /myApp/res/screen/ios. We place them there in case we need to remove and re-add the platforms/ios folder in the future (which would delete the image files). So this is just a safe place to store the images.

3. Open myapp/platforms/ios/myapp/images.xcassets/LaunchImage.launchimage and delete the png files only.

4. Copy your 10 images from step 2 to this location. All of our files will have the same names as the former files, and should all be referenced in the Contents.json file there. If your filenames or file quantity changed in any way, you’ll  need to edit the Contents.json file to suit.

Xcode will automatically discover these files and use them. So we do not need to add anything to config.xml as we did in the past.

5. In Terminal:

cordova prepare ios

6. Double-click on the /myApp/platforms/ios/myApp.xcodeproj file to open it in Xcode.

7. Verify whether your screens are recognized. Click on your folder icon at upper left, then on myApp, if the myApp file structure is not already showing. Click on /Resources, then on /images.xcassets, then on LaunchImage. The pane should now show your icons in certain wells.

8. Product > Clean, then Product > Analyze. Hopefully, there are no errors. If there are, paste the error messages into search and check out the answers there.

Test Your Own App in the Simulator

Go ahead and replace the Cordova default files in /www with your own app project, if you have one. Remove the default folders CLI had created in the /www folder: /js, /css, /img. Put all your project assets there in /www.

1. In Terminal,

cordova prepare ios

2. Double-click on myApp.xcodeproj as before.

3. When Xcode opens, choose the scheme you want (which iPhone or iPad simulator you want to use). Watch carefully. Did you see your splash screen appear? Exit your app in the sim with Hardware > Home. Do you see your myApp icon on the screen? Exit Xcode and the sim.

Note that the simulator does not have all the functionality of a real phone. For instance, if you click on your links that open the email client, nothing will happen. The link is not broken — the email client is not included. Clicking on your phone links won’t do anything either. So it’s important to check your app in a real iPhone or iPad.

Test the App in the Device

1. To test the app in an iOS device, you have to be a paid Developer, then set up the online certificates for the device.

Here is how I set up the certificates and provisional profiles in 9/2017:

In account, click on Certificates, Identifiers & Profiles.
Under Identifiers, click on App IDs.
Click on the plus icon to register a new ID.
Copy/paste your app name as it appears in config.xml into the App ID Description field.
Choose a value for the App ID Prefix, such as your Team ID.
Copy/paste the entire bundle ID (com.domainname.appname) as it appears in config.xml into the Explicit App ID Bundle ID field.
Select the services you will enable in your app, and for which you’ll be adding code for.
Click on Continue.
Double-check the information and click on Register.
This App ID is now registered to your account and can be used in your provisioning profiles. Click on Done.

Now click on All under Provisioning Profiles to create its provisioning profile.
Under Development, select option for iOS App Development.
Click Continue.
Click on the App ID dropdown and select the app ID created earlier.
Click on Continue.
Select the certificate you want to include in the provisioning profile. (These were created according to the steps in Certificates > Development.)
Click on Continue.
Now select as many devices as you will test on. (These were created in Devices > All earlier.)
Click on Continue.
For Profile Name, I put “DevProfappname”
Click Continue.
Your provisioning profile is ready. Click on Download.
Open /Downloads on your Mac. You’ll find DevProfappname.mobileprovision. Double-click on it to install it.
In the browser, click on Done.

Only after the certificates have been installed will Xcode recognize your device and add it to the scheme. Otherwise, the scheme will only show what’s available among the simulators.

You connect the device to the Mac and turn the device on. In Finder, double-click on appname.xcodeproj in /appname/platforms/ios. In Xcode, select the scheme for your device, including the device’s name, then click on the Play triangle to build and run it. At lower right you can watch the Xcode console update with your app updates. If you don’t see the console, then go to View > Debug Area > Activate Console.

If the message occurs that the device is not registered, then click for Xcode to register it for you. Then the app runs in the device.

2. There’s a second way to run it in your device. First, ios-deploy needs to be installed:

sudo npm install -g ios-deploy

Then I plug in my device and type:

cordova run ios --device

. . . it creates the .dmg file and loads it onto my device.

(In one case, when it would not run the app, I first followed the earlier step for Xcode first. Xcode installed the profile the device needed. Then this command worked.)

About the /myApp/merges Folder

What if you need to use different versions of pages for different platforms? I needed the home page of my app to be different on Android and iOS. That’s what the /myApp/merges folder is for. The /myApp/merges/ios folder is the same as your /myApp/www folder, so I moved the index.html file to the /merges/ios folder. When I did a cordova platform add android, it created a /merges/android folder. I copied the index.html file there and made the changes for the Android version. So when I do a cordova build ios or cordova build android it will use the correct file for each build.

FastClick.js is not used in Android. For this reason, I moved the fastClick.js file to both /merges/ios/js and /merges/android/js. I opened fastClick.js in /merges/android/js and deleted the contents, that way all the links in the html pages would not generate errors due to a missing file reference. It will access the file as normal, but it being blank, will not actually do anything.

When styling links for YouTube in the InAppBrowser, onclick=”” works in iOS to open a YouTube link in IAB but not in Android (it didn’t work in my Nexus 7). So I put different versions of those pages in /merges/android and /merges/ios, each page with its own link style.

If you want to use the same iOS video code in both, then you’ll need to install Chromium’s Crosswalk in the app. However, the makers of this software discontinued it in 2017. Github seems to keep it alive, however.

For another use of the /merges folder, if you have a /www/css folder and want different style sheets for each app, just create a /css folder inside each /merges platform folder (like /myApp/merges/android/css) and put the css there instead of in a /myApp/www/css folder. That will style each platform differently according to your CSS files.

To quickly test this, simply move the /www/index.html file to its /merges/ios counterpart. Open that index.html file and add the following after < body>:

< h2>This index.html page is in the /platforms/merges/ios folder.

Go ahead and test in your device with cordova build ios. The above text should appear at the top of the screen. It should not appear at all if you build for Android.

About the /myApp/hooks Folder

If you open /myApp/hooks, you’ll see a readme text file there. That folder is for adding scripts that will execute as part of your CLI operation. For instance, you can add a before_build script which will automatically add all your plugins before the actual build commences. So each time you create a new app, you’ll copy/paste that file into the new app’s /hooks/before_build folder. I’m not familiar enough with this process to explain it here, but if you already know node.js scripting, you might look into it. For instance, this page gives the hooks steps for automatically creating app icons (requires installation of Homebrew and ImageMagick): Other uses would be to add all the usual plugins.

Test Your Code

Ideally, you would have finished all these steps before you began testing your app, but I put them all down here so we could get the Cordova project up and running. I’m putting these steps here for completeness.

1. Double-check that your app meets the HIG (Human Interface Guidelines), the rules Apple uses to determine properly designed apps for the App Store. Link found in the iOS Dev Center online:

2. Double-check that your app does not go afoul of these App Review Guidelines. Link found in the iOS Dev Center online:

3. Make sure your HTML is valid.

4. Validate your Javascript.

5. You may want to minify your JS.

6. Do image optimization/compression.

7. Remove the default folders CLI created in the /www folder: /js, /css, /img if you haven’t already.

8. Make sure all html pages which use a Cordova API references this in the < head>:

 // Wait for device API libraries to load 
document.addEventListener("deviceready", onDeviceReady, false); 
// device APIs are available

function onDeviceReady() {


Don’t just copy/paste the above everywhere; change src=”cordova.js” to ../cordova.js or even ../../cordova.js, depending on the folder the page is located.

9. [Personal note] Don’t forget to add the JavaScript search function to the app:

Update Cordova

1. If you encounter issues with an individual plugin, by all means let your debugging include removing the plugin and adding it again. To do that, follow these steps:

a. In terminal: cordova plugin ls to see the plugins installed. Highlight the plugin you want to remove, and copy it.

b. In terminal: cordova plugin rm and paste in the copied plugin (like this: cordova plugin rm cordova-plugin-inappbrowser). Hit Enter.

c. To install again, in terminal: cordova plugin add and paste in the copied plugin (like this: cordova plugin rm cordova-plugin-inappbrowser). Hit Enter.

Note that Cordova does not have a way to update plugins. If you know of an updated plugin, then you simply following the a, b, c steps above to install the new plugin version.

2. If you need to update Cordova, then do this way:

npm update -g cordova

3. To update a particular platform (perform this command one at a time for each platform):

cordova platform update ios

Add Screenshots for App Store

The App Store used to require a screenshot for each size of device your app supports. No longer. If you upload a set of the larger size iPhone screen, it will be applied to the smaller screen sizes as well. So if you upload for the 4.7 inch screen, Apple will populate it for the 4 inch and 3.5 inch screens too. Same with the iPad screens.

You can also add up to three videos of the app now. They can be up to 30 seconds long. You can download any of a number of free video capture apps to your device and capture the action. Please see App Previews link below for information before making any videos.


App Previews (videos):

I. Getting screen shots of your app

1. In Xcode, set the simulator display to iPad Pro (12.9 inch) and Run.

2. After the Simulator starts and shows your app, you can go to Window > Scale, and choose a scale that allows you to comfortably navigate from screen to screen.

3. When you want to capture a screen, go to Window > Scale, and select 100%. You must select 100% for the capture even if it doesn’t fit on your screen or it won’t be captured at the correct size.

4. Click on Edit > Copy Screen

5. Open your Preview app in your Mac and select Done to dismiss that screen.

6. In Preview, click on File > New from Clipboard. It will faithfully save a screen in the size Apple wants for the upload, even if your browser screen size is smaller. Now File > Move To… with a descriptive name, like screengrab-lg-home.png and choose your Desktop. You can drag them into the final folder later. Go ahead and follow these steps for up to ten images. Close the sim window when done.

7. Back in Xcode, choose the iPhone 6s Plus and run. Grab up to ten more screens as in step 6 (now at 1242 x 2208 px). Those can be the same as the previous screens, but named screengrab-sm-home.png (so you’ll tell the difference when time to drag them into iTunes Connect.) When done, exit the Simulator. You can save all these in the backup myApp/res folder or wherever you store your app assets.

II. Adding screen shots to iTunes Connect

1. In iTunes Connect, you’ll choose the iPad button and slide up to five iPad screenshots to the box. Click Save.

Choose the iPhone button and slide up to five iPhone 6 Plus (5.5 Inch) screen shots to the box. Click Save.

2. Click on the Media Manager text link below the screen shots. Scroll down until you see the 9.7-Inch Display box and make sure “Use 12.9-Inch Display” is checked.

3. Scroll to the top and select “iOS App …” to the left of “Media Manager” to return to the previous screen.

4. Scroll down and choose the “Use 5.5-Inch Display” checkbox wherever it applies to those smaller screen sized devices. If your responsive design shifts for a smaller size, you should provide screen shots for those versions.

More about testing

iExplorer App

This app lets you navigate your device’s folder on the desktop. This was good when I wanted to check if the camera shot a picture and what image name it was given. Good also to check the contents of a database. It’s free to use as a demo.


Desktop Safari Web Inspector

Using the Safari browser, you can install your app on your iOS device and monitor its usage on your desktop monitor, including console feedback.


Google Chrome Dev Tools

Open Google Chrome, hit the hamburger options icon > Tools > Developer tools, and click on the mobile device icon. Select various devices from the drop-down menu to see your app in different device configurations.


Other Ways to Test

1. You can run the project in a web server via CLI (although you can’t test all the plugins this way):

cordova prepare ios
cordova serve ios

Open a web browser like Chrome or Firefox and paste the following into the URL field:


Open Firebug or Developer tools, then click on the ios link. Run your code thoroughly to look for problems. When finished, click on the Terminal screen to select it, then on Control + C keys to terminate the server.

I noticed that Developer Tools could not find cordova.js using the cordova serve method. That file is created in the /platforms folder. So you can open platforms/ios/www/index.html in a browser to test.

2. For more testing possibilities, use the weinre (Web Inspector Remote) software at

3. Nice article:

Get rid of the .DS_Store files


I don’t want to clog my app with the countless .DS_Store files that the Mac creates, so I’m using this code to delete them in the project.

1. Start the Terminal at your project’s root folder, /myApp

2. Copy this code into the terminal window:

rm -f .DS_Store

There is no step 3. Your files are gone in all folders in the project.

Xcode Settings for Deployment to App Store

These are the settings to change in Xcode to produce the file you’ll upload to the App Store. You do these steps after setting up Development and Distribution provisional files online.

Read this article to see if there are steps you need to take with your build.json file:

1. Double-click on your .xcodeproj file to open in Xcode.

When double-clicking on xcodeproj name, I got this error: “Project /Users/Steve/Documents/app Name/platforms/ios/app Name.xcodeproj cannot be opened because the project file cannot be parsed.” Xcode did not like the space in the name where I put it in config.xml.
a. I removed space in <name></name> in config.xml.
b. cordova platform rm ios
c. cordova platform add ios
d. cordova prepare ios.
e. Double-clicking on file opened it in Xcode normally.

2. Click on the filename at far left. The pane at right updates and shows: PROJECT/MyApp and TARGETS/myApp (that’s how I named it in config.xml <name=).

3. Click on TARGETS myApp, then on General settings. Make sure the Version is correct. For Signing, you generally want to have “Automatic manage signing” checked. When you get errors, sometimes you’ll have to uncheck this and manually enter the signing.

4. For Signing (Debug) and Signing (Release), select the Development profile for each. (In the past we would choose a separate Distributor profile for the release.)

5. For Deployment info, Devices, notice the iPhone and iPad buttons; iPhone is selected. Choose which size you are supporting; choose Universal if it is for iPhone/iPod and iPad devices. Below that, choose all the orientations your device supports.

6. Below that, check if your app requires full screen.

7. Now select the iPad button and go through the same choices.

“Submit for Review”

1. Fill out the Application Assets Template located here:

2. You’ll need to go online to the Apple Developer site at (preferably using the Safari browser), sign in, and click on the iTunes Connect link. Click on Manage Your Applications and either Add New App, or choose an existing app to upgrade. Follow the steps online and transfer all the information into the fields from the Application Assets Template you just filled out, as well as the screengrabs you made.

Steps I took to upload a revised app:

  1. Opened Safari web browser (for best experience with Apple).
  2. Clicked on Member Center and signed in.
  3. iTunes Connect, sign in again.
  4. My Apps icon.
  5. Select the app icon to update.
  6. Clicked on + VERSION OR PLATFORM and chose iOS. Then enter the store version number you have in config.xml (“8.0”). Click Create.
  7. Click on the screenshots tabs to make sure all are filled.
  8. Add info in What’s New box.
  9. Update any other information you see on the page. In Notes? you can write anything that will help the reviewer with checking your app.
  10. At the bottom, check whether you want to release the app manually or as soon as it has been approved.
  11. Click on Save at top. Leave this page open and go back to Xcode.
  12. Unhook your device from the computer (if it was connected). Follow the next steps.

Upload a Binary to the App Store

I. In Xcode

1. A binary of the app is the compiled version of the app that is made up of 0’s and 1’s. To compile your app for the App Store, first make sure your device is unconnected, and you are signed in to the App Store online.

2. If you made any last-minute changes to the Cordova project, do a cordova prepare ios command in a terminal window.

3. In Xcode, do a Product > Clean while holding down the option key.

4. Then set Product > Destination > Generic iOS Device.

5. Then do a Product > Analyze and wait for the app to build.

a. I got the errors: “… has conflicting provisioning settings. … is automatically signed for development, but a conflicting code signing identity iPhone Distribution has been manually specified. Set the code signing identity value to “iPhone Developer” in the built settings editor, or switch to manual signing in the project editor.”
“Code signing is required for product type ‘Application’ in SDK ‘iOS 10.2′” What worked: In Xcode, click on the app name folder. Click app name under TARGETS. Uncheck to Automatically manage signing. For both Signing (Debug) and Signing (Release), choose your development profile.

b. I got the error: “Signing for myApp requires a development team. Select a development team in the project editor.” What worked: Click on folder icon at left to show project name and files. Click on project name. Pane at right updates with PROJECT and TARGETS. Click on name under TARGETS. For Signing, select a team for the Team dropdown.

If you get more than one error at a time, just fix one then Analyze again.

6. When you get no more errors, Product > Archive. The Organizer window should open (if it doesn’t: Window > Organizer).

7. Click on your app name in Organizer, make sure of the version, then click on Upload to App Store…

8. Select a Distribution Certificate. You made this when you made your Developers Certificate earlier on Certificates in iTunes Connect. If not, go there and make one.

9. Select the Profile. Click on Download Profile if need be. Next.

10. Type in your login keychain password. Click Upload. You should get the welcome message, “Uploading to App Store.”

If you get more errors, check out the Troubleshooting section of the App Distribution Guide by Apple:

When finished, you’ll get a Submission Successful screen. Hit Done.

II. In iTunes Connect

1. Now switch to your app’s Apple developer page in iTunes Connect, and review the links and form field boxes to make sure you have everything entered. Upload your screengrabs, videos, etc.

2. Under Prepare for Submission, scroll way down, and click on Build +. You’ll need to wait a long while before it appears if your app is still processing. There’s no progress bar, so just click on the other links at left and switch back until you see the + next to Build. Click on it, then select your app, then Done. You might get a “Processing” note at times in this box; there’s no progress bar, so just come back later and refresh the screen to check.

3. If you successfully hit Done, you should see the App Store Icon appear below. Scroll up and hit Save.

4. Click on Submit for Review. Answer the questions on the page and hit Submit. The status at upper left should now say Waiting For Review. You may now log off of the Apple site. At this point it’s a waiting game as Apple techs review your app. Apple will actually send you emails and notifications in your device on the changing status of your app. While waiting, you can perform the next few steps.

Back up your files

1. Open Keychain Access (click on the magnifier icon at top right of your desktop and type in “keychain” and select the app). Right-click on the certificates and export each one to your computer (giving each one a name similar to the name in the Keychain Access line), then send it off to a safe backup location. Warning: if these files are lost, you won’t be able to upload successive versions of your apps to the App Store.

2. Back up your password files. Go to /Users/[name]/Library/Keychains and copy the .keychain files there to a safe place. /Library is a hidden folder.

To show the hidden files, type in Terminal:

defaults write AppleShowAllFiles TRUE

. . . and hit Return. Then type in Terminal:

killall Finder

. . . and hit Return. The desktop will go blank, then after a while will refresh. Open the Documents folder, then in Finder, Go > Enclosing Folder, and see the hidden files in gray, including /Library.

To hide the hidden files, repeat both commands, but substitute FALSE in place of TRUE.

Mac®, OS X®, Apple®, Xcode®, App Store℠, iPad®, iPhone®, iPod® and Finder® are trademarks of Apple Inc.

9 thoughts on “Using Cordova CLI on Mac OS X to build iOS apps – updated 3/2018

  1. Pingback: Using PhoneGap 3.0 CLI on Mac OS X to Build iOS and Android Projects | iPhone Dev Log

  2. “The pane at right updates and shows: PROJECT/MyApp and TARGETS/MyApp (that’s how I named it in config.xml <name=)". — Im a bit confused what exactly is "it"? What would PROJECT/MyApp and TARGETS/MyApp be named if you didn't change there names? (Im new to cordova)

  3. I am trying to use cordova cli on a mac os x el capitan 10.11. I’ve installed npm, cordova cli, ios deploy, ios sim and have xcode. But when I enter the command “cordova requirements” it shows that :

    Requirements check results for ios:
    Apple OS X: installed darwin
    Xcode: not installed
    xcode-select: error: tool ‘xcodebuild’ requires Xcode, but active developer
    directory ‘/Library/Developer/CommandLineTools’ is a command line tools instance ios-deploy: not installed

    ios-deploy was not found. Please download, build and install version 1.8.3 or greater from into your path, or do ‘npm install -g ios-deploy’
    Error: Some of requirements check failed
    I have all of the above installed on my mac, still getting these errors, please?


  4. Pingback: Updated March 2018 | iPhone Dev Log

  5. Pingback: Workflow | iPhone Dev Log

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.