Using Cordova CLI on Mac OS X to build iOS apps – updated 4/2017


This article gets you up to speed on how to integrate your HTML/CSS/JS app with PhoneGap/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 https://iphonedevlog.wordpress.com/2013/08/16/using-phonegap-3-0-cli-on-mac-osx-10-to-build-ios-and-android-projects/ 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:
http://www.apple.com/osx/apps/app-store.html 

Before you can install the app you create with PhoneGap 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 (https://developer.apple.com/programs/ios/), 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.

Although you can develop the HTML/CSS/JS portion of an iPhone app on a Windows machine, you’ll still need a Mac with Xcode to convert the code to the binary that is uploaded to the App Store. You need a Mac to make iPhone apps. (PhoneGap Build can create this binary for you from your files, but you still need a Mac to download and install certain certificate files.)

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: https://developer.apple.com/app-store/review/ 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: https://iphonedevlog.wordpress.com/2014/06/25/updating-and-reverting-to-different-cordova-phonegap-versions/

Pay attention to the inconsistencies in the early PhoneGap documentation between the use of “phonegap” and “cordova” in the command line. For instance, the Command-line Interface online page uses “phonegap” while the InAppBrowser API online page uses “cordova.” They are not interchangeable when using CLI. As seen in the above command, we are asking to download “cordova.” So we would replace all instances of “phonegap” in the documentation with “cordova,” or the command will generate a “not found”-type error.

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 /PhonegapApps
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.” Some online tutorials and PhoneGap documentation will tell you to use “phonegap;” in that case, change it to “cordova” and it should work fine.

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 /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 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: https://github.com/jessemonroy650/top-phonegap-mistakes/blob/master/new-to-Phonegap.md

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).

Dec. 2015: There were many warnings in Xcode for CordovaLibs regarding stuff being deprecated in Cordova 3.9.2, including ‘whitelist’ code, even though my version is 5.4.1. Response: simply double-click on “Update to recommended…” then on Perform Changes. Ignore all other warnings.

Add the Whitelist Plugin

This 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.)

Resource:
http://code.tutsplus.com/articles/apple-tightens-security-with-app-transport-security–cms-24420

Add the InAppBrowser Plugin

Cordova 6.4.0 automatically includes the inAppBrowser and adds it to the config.xml file, so just skip down to Step II, 2.

Cordova has the ability to add more features to the app via plugins. Cordova does not automatically install every feature and that keeps the code footprint down. Plugins:  https://www.npmjs.com/search?q=ecosystem%3Acordova

We’ll incorporate the InAppBrowser (IAB) API. The IAB allows us to open external URL links from within the app. Some developers would prefer this over the default of leaving the app and opening a web browser, shutting down the web browser when done, then restarting the app again. The IAB opens the link in its own frame, with a Done button bringing the user back into the app.

We first download the IAB as a plugin using CLI.

Resource:
https://www.npmjs.com/package/cordova-plugin-inappbrowser

Step I: download the plug-in

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

cordova plugin add cordova-plugin-inappbrowser --save

2. Verify that the plugin is installed with the ls (list) command:

cordova plugin ls

Step II: add to the config.xml file

Resource: http://cordova.apache.org/docs/en/latest/config_ref/index.html

1. Open the myApp/www/config.xml file in a text editor (I use TextWrangler). Before Cordova CLI 5.0.0, we had to add lines like the following, but no more:

<feature name="InAppBrowser">
 <param name="ios-package" value="CDVInAppBrowser" />
</feature>

The “–save” command in step 1 wrote the Cordova plugin lines for you.

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. Later I entered “My App” in <name></name> and later again changed it to “myApp” to investigated what changed in the build.

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 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:

<!DOCTYPE HTML>
<html>
<head>
<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: https://ssl.gstatic.com 'unsafe-eval'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *">
<title>
App Name
</title>

< 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() {
// navigator.splashscreen.show();
}

(WordPress no longer retains 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.)

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:

http://www.raymondcamden.com/2015/05/25/important-information-about-cordova-5

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

http://content-security-policy.com/

4. Now let’s test it. Open PhoneGap’s /myApp/www/index.html page and replace portions with the following lines in these inAppBrowser instructions: https://iphonedevlog.wordpress.com/2013/06/27/implementing-inappbrowser-into-a-cordova-phonegap-project/

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.

Add the Dialogs Plugin (optional)

Resource: https://www.npmjs.com/package/cordova-plugin-dialogs

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() { 

}
 </script>

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
 window.open('https://iphonedevlog.wordpress.com', '_blank');
}
function confirmation() {
navigator.notification.alert(
 '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 containing its own purpose.

I changed this standard alert:

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

… to the new style:

navigator.notification.alert(
 '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) {
 removeSet();
 }
 else {
 close();
 }
};

… 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. With FastClick.js, you’ll use “click” instead of “touchstart” for your links.

Resource:
https://github.com/ftlabs/fastclick

1. 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() {
        FastClick.attach(document.body);
    }, false);
}
</script>

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.

Add Your Icons

Resources:
http://cordova.apache.org/docs/en/latest/config_ref/images.html
https://developer.apple.com/library/iOs/qa/qa1686/_index.html

1. Use the free online service at http://makeappicon.com 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.

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.

Add Your Launch Images (Splash Screens)

Resources:
http://cordova.apache.org/docs/en/latest/config_ref/images.html
https://github.com/apache/cordova-plugin-splashscreen

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 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 width. Save as Default-Landscape@2x~ipad.png (2048 x x1536).

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() {
 navigator.splashscreen.hide();
}

2. Put these 10 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/mypp/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 stackexchange.com 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.

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. 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 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 some versions of 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=”window.openwindow.open()” 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 Android app.

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): https://github.com/AlexDisler/cordova-icon. 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: https://developer.apple.com/devcenter/ios/index.action

2. Double-check that your app does not go afoul of these App Review Guidelines. Link found in the iOS Dev Center online: https://developer.apple.com/devcenter/ios/index.action

3. Make sure your HTML is valid. http://validator.w3.org/

4. Validate your Javascript. http://www.javascriptlint.com/online_lint.php

5. You may want to minify your JS. http://www.minifyjs.com/javascript-compressor/

6. Do image optimization/compression. http://imageoptim.com/

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

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

 
// 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.

9. [Personal note] Don’t forget to add the JavaScript search function to the app: https://iphonedevlog.wordpress.com/2013/09/02/easily-add-search-functions-to-your-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

Update Nov. 2016 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.

Resource: https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Appendices/Properties.html#//apple_ref/doc/writerid/itc_screenshot_properties

Images must be at least 72 dpi, in the RGB color space, and the file must be .jpeg, .jpg, .tif, .tiff, or .png. Choose up to five. Again, you don’t need to make these screens individually anymore. See steps I and II below.

iPhone 3+4 (3.5 Inch)
640 x 960

iPhone 5 (4 Inch)
640 x 1136

iPhone 6 (4.7 Inch)
750 x 1334

iPhone 6 Plus (5.5 Inch)
1242 x 2208

iPad (Air and Mini Retina)
1536 x 2048

iPad Pro (12.9 inch and 9.7 inch
2048 x 2732

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 or it won’t be captured at the correct size.

4. Click on Edit > Copy Screen

5. Open your Preview app in your Mac.

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! Go ahead and follow these steps for up to five pages.

7. When done in the Simulator, go to Hardware > iOS 10.2 > iPhone 6 Plus and grab more up to five more screens. When done, exit the Simulator.

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.

Resource:
http://www.macroplant.com/iexplorer/

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.

Resource:
https://iphonedevlog.wordpress.com/2014/05/02/using-the-desktop-safari-web-inspector-to-debug-your-installed-app/

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.

Resource:
http://blog.chromium.org/2014/09/responsive-web-design-with-devtools.html

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:

http://localhost:8000

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 http://people.apache.org/~pmuellr/weinre/docs/latest/

3. Nice article: http://www.smashingmagazine.com/2014/09/03/testing-mobile-emulators-simulators-remote-debugging/

Get rid of the .DS_Store files

Resource: http://www.wikihow.com/Remove-.Ds_Store-Files-on-Mac-Os-X

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: https://dpogue.ca/articles/cordova-xcode8.html

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: http://wp.me/pyIb9-1o

2. You’ll need to go online to the Apple Developer site at http://developer.apple.com/ (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 Jan. 2016 to upload a revised app:

  1. Opened Safari web browser (necessary 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

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.
2. If you made any last-minute changes to the PhoneGap 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 > Archive and wait for the app to build.

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: Click on app name folder. Click app name in TARGET. Uncheck to Automatically manage signing. For both Signing (Debug) and Signing (Release), choose your development profile.

6. 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 Dev Team for provisioning (I choose my name). Click Choose.
9. Next screen will list myApp.app and Provisioning Profile. Check the PP and read below.

At this point, sometimes my PP is XC: and that’s not right. In that case, hit Cancel, right-click on the app name, and choose Delete Archive. Minimize Organizer, then in Xcode click on appName under PROJECT and under Code Signing you’ll need to select the correct Code Signing ID for Release, both rows. (It should not be iOS Developer.) Now go back to step 3 and try again.

Assuming your PP is correct, hit Submit. Do something else while the Archive is being uploaded.

If you get more errors, check out the Troubleshooting section of the App Distribution Guide by Apple: https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40012582-CH1-SW1

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

7. Now switch to your app’s page, scroll way down, and click on Build +. You’ll need to wait a while before it appears if your app is still processing. Select your app, then Done. You’ll get a “Processing” note at times in this box; just come back later and refresh the screen.

8. If you successfully hit Done, then scroll up and hit Save, then Submit for Review.

9. 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 com.apple.finder 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.

3. Now would be a good time to create a “snapshot” in Xcode of your work at this point in time (in Xcode, File > Create Snapshot). A Snapshot is a copy of the project stored away. You’ll be able to revert to this version at a later date if you need to. If everything is working fine, then do a File > Create Snapshot of your current working project.

You can delete these snapshots by going to Window > Organizer, click on Projects at top, then on the project name at left. After clicking on a Snapshot, click on the Delete Snapshot icon at lower right. This will free up a lot of memory after you’re sure you will no longer need the earlier versions. If you need to revert to an earlier version (snapshot) of the project, you will first create a new folder in Finder, then click on the Restore Snapshot icon to save it to that folder. You’ll have two versions of the project; this way the reverted version will not overwrite the previous version.

Further Recommended Steps

If you are going to be involved with PhoneGap regularly, keep up to date with the release announcements of upcoming versions, updated plugins, and other news.

Familiarize yourself with the Cordova site: http://cordova.apache.org/

Read the PhoneGap Blog: http://phonegap.com/blog/

Subscribe to the PhoneGap Twitter feed: http://twitter.com/phonegap

Be friends on Facebook: http://www.facebook.com/PhoneGap

Join Google Groups: https://groups.google.com/forum/#!forum/phonegap

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

Advertisements

5 thoughts on “Using Cordova CLI on Mac OS X to build iOS apps – updated 4/2017

  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 https://github.com/phonegap/ios-deploy 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?

    Thanks

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s