Fix for iTunes Store Rejected – This bundle is invalid – The Info.plist file is missing or could not be parsed

Did you get the below email after trying to submit your NativeScript iOS app to iTunes Connect?

Dear developer,

We have discovered one or more issues with your recent delivery for “#####”. To process your delivery, the following issues must be corrected:

This bundle is invalid – The Info.plist file is missing or could not be parsed. Please check it for embedded control characters.

Once these issues have been corrected, you can then redeliver the corrected binary.

Regards,

The App Store team

It can be really irritating but the fix is pretty simple.  This happens when odd characters or weird adjustments are made dynamically to the plist.info file attached to your bundle.  To get rid of this annoying rejection you should do a few things.

  1. Make sure you are setting as much info as you can manually in your app/App_Resources/iOS/info.plist file.  This file is used to generate the xcode.project file’s included plist.  Avoid adjusting the generated plist.info file as much as possible and do this pre-emptively before each build including updating your CFBundleShortVersionString and CFBundleVersion keys to latest version.
  2. Now runs tns platform remove ios then re-add with tns platform add ios
  3. Finally run tns prepare ios

You should be good to go and no more rejection (for that at least)!

NativeScript iOS Push Notifications & How to Get Your Device Token When Testing & Debugging in Xcode 8

I found all the articles and frameworks and this still took me quite some time to figure out.  As far as I can tell this is easiest to do using Xcode 8.  Some preliminary items you’ve probably already taken care of if you’ve found yourself here:

Ok, you should be ready to get busy.

Adding The Push Plugin Code To Your Project

From what I can tell it’s not so important where this code is added but seems ideal to put it in the main page js file, the first that loads.  You need to use an observable and bind it to your page.  I had an app that was well into version 2 that I wanted to add push notifications to.  It was setup as many examples are from a year or more ago using

exports.loaded = function(args) { 
  main code here that is run when the first page is loaded  
}

All the examples online use a main-page-view.js observable that’s instantiated in the other main js file and it’s all very complex.  What it boils down to is you need to reference the main observable that’s being bound to your page in the var self = xxx line of the push notifications example code.  In its shortest form you would do something like this:

https://gist.github.com/ChrisFlannagan/8ce46cfd02ab32a291bbeb026624f2a7

What’s super import here is the var self = pageData.  We are putting our observable into a variable called “self” that is used in the push notifications code from the readme.

I was just copying the code into my exports.loaded function and kept getting an error like self.set is not a function and was getting really irritated.  So do what I did above or start a fresh project and copy from the sample push plugin repo here.

Getting Your Device Token

In order to test notifications you need to run your app on an actual device.  So plugin your iPhone or iPad and get ready to run your app on it through either Xcode or tns command line.  I always get confused on how to select the right device on command line so I just use Xcode.

You will also need to make sure you have all the example code in place for registering your device.  I’ve built something you can copy here, just make sure that exports.loaded is initiated on the first page load.  The main xml would look like this in the top tag:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="loaded">

I’ll also embed the full javascript sample code at the bottom of this post so you don’t have to click out of here.

Now you need to get your device token from your iphone/ipad which you will need to use in an app like Easy APNs Provider in order to send test notifications to your phone.  I could not find any functionality in the nativescript plugin but on the link I shared earlier the fella shows how to do it in swift.  These lines here:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    print("DEVICE TOKEN = \(deviceToken)")
}

You can see the long ass function name there.  I found that function in the nativescript plugin files in node_modules.  So you need to temporarily edit (I know, I know) the file and add a console.log to it.  In node_modules/nativescript-push-notifications/push-plugin.ios.js on, at least in the current version, line 41 you will see

var token = result.userInfo.objectForKey('message');

Under that add a console log:

var token = result.userInfo.objectForKey('message');
console.log(token);

Now when you run the app and accept the push notifications alert it will log in your terminal the device token.  DO NOT FORGET to edit that console log out.  Gotta keep them node_modules pure ya know.

Testing It Out

If you did everything right you can use the app I linked to earlier, Easy APNs Provider, and run some tests.  It worked flawlessly for me once I got the code running.  Good luck! Hit me up if you get stuck @ChrisFlanny.  Here’s a full sample code for doing a simple implementation inside an exported function:

https://gist.github.com/ChrisFlannagan/7f352ec635f1e4dc193ed62e4128609c

Update Your NativeScript Plugins

I have an app I’ve been developing for 10 months now.  It’s been in the iTunes store since this past September.  I’ve been rehashing how the photo capture and gallery system works for a couple of months now and kept having random crashes, or after releasing and testing the live version on my phone it would bugger out or act weird.

I noticed in the console I was getting a warning.  It technically wasn’t breaking the app but I had a hunch it was causing the random freak outs.

CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.

I tried googling a solution but it was way over my head and not really related to coding in NativeScript.  So I google uncommitted CATransaction NativeScript.  I found a thread on a repo that dealt with using a background http thread.  My photo gallery was highly dependent on NativeScript Background HTTP plugin.

I tns plugin remove nativescript-background-http then tns add plugin nativescript-background-http and it installed version 2.5.1 which was released two weeks ago.  Instantly that issue was gone and the photo section was running so much smoother.

I’m not sure what changed, but these plugin devs (the good ones at least) are on top of it.  Get the latest versions of your plugins!

Getting Up To Speed With NativeScript 2.3, Xcode 8 and iOS 10

tns livesync ios --emulator --watch

Unsupported version Xcode 8

Oh no …

It’s That Time

The iPhone 7 is out along with iOS 10 and things have changed.  It hit me today when I was toying with my company’s app for the first time since upgrading Xcode.

So what do? Well, the first thing I needed to solve was getting my apps running in Simulator again.  I opened up Xcode and built my app in there instead of the command line tns.  I ran it on iPhone 7 Simulator and everything popped up and seemed to be working until it crashed right away on launch.

Upgrade NativeScript to “Next”

I uninstalled NS and the tns modules and reinstalled completely using the next version (2.4).

npm uninstall nativescript -g
npm uninstall tns-core-modules
npm install nativescript@next -g
npm install tns-core-modules@next

Then I removed the ios platform from my app and added it back.  Voila, things were loading up.  Thing is, I’m lying a little, I forgot to install the @next version of tns-core-modules and even though the app was opening certain things weren’t working like trying to set the src of an Image via javascript.

Properties Not Methods

So something big is happening.  Xcode is changing some big core items from using methods to initiate and instead using properties.  For example I use local-notifications plugin to send phone notifications.  I was erroring out with:

NSNotificationCenter.defaultCenter() is not a function

Apparently that is now a property so I had to adjust the module’s code in local-notifications.ios.js to

NSNotificationCenter.defaultCenter

And it works just fine now.  Or so I believe, no more errors but haven’t tested it thoroughly.

plist.info Permission Changes

Next the app crashes when I try to open the camera.  I’m getting errors saying there’s permission issues.  Turns out I need to have some new info in app/App_Resources/plist.info

<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>

More To Come

This is all so far but I’ll be sure to add more information as I encounter it.

 

Multiple Overlapping Layers of Transparent PNG Images Using AbsoluteLayout in NativeScript

Say you have an image of a face in your app.  There are multiple quadrants you want a user to be able to select.  When they select, it should highlight that area.  You want the user to have the ability to select any combination of these quadrants.

Stacking Images In AbsoluteLayout

Let’s go over the xml layout first.  I accomplished this task using an AbsoluteLayout with four Image views inside it like so.

https://gist.github.com/ChrisFlannagan/ca79529e943350c093f33e13023a03c7

Notice I set the width to 100% but not height. In my full code the height is set in a GridLayout for row 3, but you can set height to 100% or a pixel amount.

I placed a plain face photo as the background for the AbsoluteLayout.  Then I have four images for different quadrants of the face.  These have their absolute position set to 0px top and 0px left.  My overlaying images are the exact same size as the background image of my AbsoluteLayout so I want them to fit exactly over top.

I set the width to the parent element width, this way I know it will translate to different screen sizes.  I get the parent width in my javascript file then set it using this variable parentWidth.

Each image can be turned on or off by setting the visibility to collapsed or visible.  This is controlled in the javascript by the binding object along with the width.  See below:

https://gist.github.com/ChrisFlannagan/c94006689d4783f6667169d53e4f7beb

When the page is loaded I set my initial variables in pageData then turn that Observable into the binding data for the page.  So initially all images will be collapsed (turned off).

Gestures

Next I set gesture detection to my AbsoluteLayout that has been given the id “main-layout” and attached to the variable “quad.” I measure where the touch took place then if it’s in an images quadrant it toggles the collapsed/visible state.  The images are all positioned absolutely so they layer on top of each other.

 

Add Two Color Linear Gradient Backgrounds To View Elements In NativeScript

Since the css linear-gradient isn’t part of NativeScript core yet I went looking for the ability to do this online.  I found a git conversation over at https://github.com/NativeScript/NativeScript/issues/539 that discussed and shared some code.

The code doesn’t work on iOS as expected.  There were some typos in the code that need to be adjusted and wrong variables.  I’ve made those adjustments and you can copy below a functioning version.

I added it to a .js file in my /app directory called grad-bg.js.  Simply load this .js file into your page’s javascript code with:

var gradients = require("~/grad-bg.js");

Import the function via the require method.  Then in your page loaded function call the function on your view.  Make sure to set the view’s id in your xml file and use that id here as the second parameter:

https://gist.github.com/ChrisFlannagan/9fc4b8e2ef871208abcb7f15018cd6ec

Here’s the full javascript function for linearGradient

https://gist.github.com/ChrisFlannagan/5dd5ca61ac01b15cf60b87dda20beaba

Repo: https://github.com/ChrisFlannagan/nativescript-gradient-background

The WP Crowd: Build Data Driven IOS & Android Apps With WordPress REST API & NativeScript – Part 1

I’ve started a new series over at The WP Crowd about putting WordPress & NativeScript to work together building REST API data driven apps.

Build Data Driven iOS & Android Apps With WordPress REST API & NativeScript – Part 1

Animate Image Or View Circular Motion In NativeScript

quick-demo.mov video file

I haven’t taken calculus in years and I haven’t needed it since college.  But today I did.  I needed to animate an object going in a circular motion over a graphic of a face in an iPhone/iOS app I’m developing.  These examples are purely wire framed with no official graphics or design.

What You Need

  • An AbsoluteLayout view
  • An Image view (or whatever you’d like really) inside that AbsoluteLayout
  • A starting x and y coordinate which will be the center of your circular path
  • Radius of the circle you want for your path
  • Angle (or animation speed)

Layout

 

We are going to build our layout dynamically.  I found this to be the best method for sizing things and positioning our elements.  Let’s take a look at that code.

First we need some xml to hold our generated layout items.  A simple stack layout works here, I use the horizonalAlignment and verticalAlignment to fill up the screen.  Well, it’s supposed to but doesn’t seem to function just right depending on the xml around it.  Still, it will work well enough for our demo here.

<StackLayout id="main-layout" orientation="vertical"
      horizotnalAlignment="stretch" veritcalAlignment="stretch">
</StackLayout>

Let’s fill that with some elements we want for our circular animation.  I’ve loaded this example code up with comments to explain what’s happening but I’ll point some important bits after this code block.

https://gist.github.com/ChrisFlannagan/56c55de015c0ee55b9310d3b542ac8a4

So our angle variable in combination with our duration speed is what controls the speed of our animation.  Each “frame” is 1000 milliseconds which is set at the very end of the setInterval function’s code block, the second parameter.

Our call to .animate() has duration: 1000 ms as well so the time it will take to transition to the next point on the circle is also 1 second.  If you think about this that means it’s going to move in a straight line from one point on the circle to the next as in this graph below.  Within 1 second, before the next frame’s location on the circle path is calculated, it animates the transition between points.

Imagine the little red circles are the calculated points transitioned to every 1 second of setInterval().  Our object moves in a straight line between them over the course of that one second.

circle-animation-lines

Starting Coordinates

The oddest problem I encountered was that my animated object shot to the outer radius of the circle from the center of it before starting reach the initial calculated frame.  What was happening is that the object is animated to it’s next frame based on it’s original x and y position.  So each calculation is based on that.  Since I start at a 0 degree angle the y axis doesn’t change when it starts but the x axis does.

I tried changing the xOrigin property to 50 (the radius) less than where I plotted it in hopes this would allow all future transition calculations to be based on that and it would seamlessly animate from the beginning but that didn’t seem to work.  So you can see in the code my solution is to subtract 50 from the x when calculated and it gives a calculation like the xOrigin is 50 less.  This seems to work just fine.

Adding Controls

In my project I have a start and stop button.  It also has a timer countdown which is not complete yet so the code isn’t going to do anything when the timer runs out.  You can see it in the main video above. I’ll post that full code below so maybe you can use some of the functionality.  It’s not commented as cleanly but notice in the xml that there are start and stop buttons with “tap” parameter which calls the respective functions in our .js file.

https://gist.github.com/ChrisFlannagan/3e74f87b5769b1f00f4f48f28faf3107

And the javascript

https://gist.github.com/ChrisFlannagan/b1e8c803fa3136e26bfca406ab5c35e8