Update on my app

So I was hoping to be done last week (before I got back to work) however, I wasn’t. Its started and I’m really far along though! Just starting and blogging about it was definitely a motivator, so I’m blogging about its progress again to keep myself on track.

TLDR: I learned to use a prototyping tool for iOS development. I’m hoping to have a working prototype next week.

What challenges did I run into building the app that quickly?

Surprisingly, at least to me, it was design! The reason I say that is because as a long time web developer I am used to prototyping web application ideas by simply throwing a backend together and then pages that basically have the functionality I need, but no real layout. Since its a web app. I usually have content and links. Making updates to it to eventually bring the design and user experience in – isn’t very difficult.

However, this way of working fell apart very quickly with iOS.

I couldn’t just throw data on the page and create a link to the next page. I had to consider how the data was being presented. I also had to consider how the transition from one page to another occurred. With a webpage, its a link. That’s it. With iOS, I could be in a navigation controller like Mail, I could bring up a modal window, or I could even animate and flip the screen like a Weather app. These decisions had to be made up front otherwise it was going to be harder and harder to change later – harder = time = expensive.

So I stepped back and started laying out the application in a prototyping tool. I started using Storyboards right in iOS. They were ok, but the process wasn’t creative enough. It wasn’t free flowing and building and running seemed time consuming.

I eventually settled on AppCooker.

Mockup-iPhone-Screens-View1AppCooker worked really well for me. Its an iPad app that lets you build out an entire iOS application and run through it. I can create clickable zones, choose transitions and I can try navigational constructs cheaply and throw them away if they don’t work. The best part is I can send the tappable prototype to someone. All they have to do is download AppTaster from the app store and try it out.

Once I had a working tappable prototype it made it much easier to build it out in Xcode. This was a big lesson learned for me for iOS development. I’ve used prototyping before on web development projects, but I haven’t always had to start there. I feel like its a mandatory starting point for iOS.

When am I going to show this thing off?

Soon! As soon as I have a working prototype I will make a video and walk through it – posting that here for you to see.


Where to start…

Ok, so I need to figure out what idea to work on.

I forgot to mention a couple other resources I picked up: The App Design Handbook and Design+Code I’m skimming them now… no time to read them cover to cover… but I need some guidance on narrowing my focus and picking the right direction.

One of the standouts is the concept of making a video for your app (mentioned in the App Design Handbook). This is interesting… basically the idea is that I should be able to come up with a video for my app. I don’t have to make it – just have to be able to plan it out. If I can – I have a well developed concept…

So that’s what I’m doing now.

I’m building an iOS app. Right now.

That’s right. I’m building an app right now.

I’ve found myself here with the precious commodity of time after doing the obligatory family visits over the holidays. I’ve always had a couple ideas, but never had the time. So here I am.

Getting started is always the hardest part… luckily I’ve been preparing for this moment for far too long… sort of an analysis paralysis kind of thing. I’ve been through a bunch of iOS online programs so I’m not completely green, stuff like iOS App Development with Swift Essential Training by lynda.com. I’ve also read a few books on the subject, Beginning iPhone Development by Apress is a good place to start if you’re just getting started – in fact I’m going to keep this at my side as I get going here – to reference the basics in case I get stuck. I’ve also purchased The Complete iOS 8 Course with Swift by Bitfountain. I’m going to reference this as well if I need to.

For the backend? I’m a rails (is it Rails?) developer. So I’ll use that. I’m gonna stub it out with hard-coded values to start… not really worrying about most of the backend until the end. I’ll push the app to Heroku so I can test it easily during development.

So what am I building? Well I have a couple ideas. I’m going to continue blogging my process and the problems I am hoping to solve, so maybe you’ll be able to figure it out… but for now… its a surprise.

Let’s get started!

XPath Query Returns No Results Using Libxml2 and GDataXmlDocument nodesForXPath

If you are using TouchXML or GDataXML for reading XML documents, you may have run into a problem with your XPath queries. I was working with the Freshbooks API to return a list of projects and it returned some fairly simple XML (I have abbreviated all the attributes of a project element for clarity):

<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="ok">
  <projects page="1" per_page="15" pages="1" total="5">
      <name>Super Fun Project</name>

So now I wanted to simply retrieve all the project elements in the response using XPath. Seemed simple enough, so this is what I wrote:

// doc is an instance of GDataXMLDocument
NSArray *projects = [doc nodesForXPath:@"//projects/project" error:nil];
NSLog(@"%d", projects.count);

My NSLog statement always returned 0 results. This started to drive me nuts. I tried several different XPath queries and still no luck. There were no errors even when I used the error outlet, and I could even loop through the elements manually and see that there were indeed project elements being returned. So what’s the problem?

The problem had to do with namespaces. The XPath query needed to be written using the correct XML namespace, so something like this:

// doc is an instance of GDataXMLDocument
NSArray *projects = [doc nodesForXPath:@"//ns:projects/ns:project" error:nil];
NSLog(@"%d", projects.count);

Great, but what is the namespace name? According to my XML response it was http://www.freshbooks.com/api/. However the GDataXMLDocument knew nothing about it.

I started digging into the source of GDataXML and came across this in the nodesForXPath method:

int result = xmlXPathRegisterNs(xpathCtx, prefix, nsPtr->href);
if (result != 0) {
    NSCAssert1(result == 0, @"GDataXMLNode XPath namespace %@ issue",prefix);

Ok… some simple debugging showed it was actually registering a namespace, but what was it called? That lead me to some code just before the xmlRegisterNs call:

if (prefix == NULL) {
    prefix = (xmlChar*) kGDataXMLXPathDefaultNamespacePrefix;

Now we’re getting somewhere. Next stop the definition of the kGDataXMLXPathDefaultNamespacePrefix constant:

// when no namespace dictionary is supplied for XPath, the default namespace
// for the evaluated tree is registered with the prefix _def_ns
_EXTERN const char* kGDataXMLXPathDefaultNamespacePrefix _INITIALIZE_AS("_def_ns");

THAT WOULD HAVE BEEN HELPFUL AN HOUR AGO… Anyway, I went ahead and changed my original XPath query to:

// doc is an instance of GDataXMLDocument
NSArray *projects = [doc nodesForXPath:@"//_def_ns:projects/_def_ns:project" error:nil];
NSLog(@"%d", projects.count);

BOOM. Now we’re cooking with gas. It correctly returned all my project elements. So the lesson learned here is that GDataXML and TouchXML will not register your namespace or use it by default. You have to use the default, or register it manually.

How do you register a namespace with GDataXML manually you ask?

// doc is an instance of GDataXMLDocument
NSDictionary *ns = [NSDictionary dictionaryWithObjectsAndKeys:@"http://www.freshbooks.com/api/", @"fb", nil];
NSArray *projects = [doc nodesForXPath:@"//fb:projects/fb:project" namespaces:ns error:nil];
NSLog(@"%d", projects.count);

And finally, if you want to programatically register a namespace using GDataXml, then you would populate your NSDictionary by iterating through the namespaces found by GDataXMLElement:

// doc is an instance of GDataXMLDocument
NSArray *namespaceURIs = [doc.rootElement namespaces];

Hopefully that saves you some time and sanity.