I really buy into the premise: drive better, be fuel efficient. But this has loads of problems and ultimately makes my driving more stressful.

After nearly three months of using Automatic I got my first perfect score last week. But not for a lack of trying. The sensor dings me for accelerations that are not sudden (it's very unforgiving for standard transmissions), dings me for breaking that is not hard, and dings me for driving 69 mph (somehow the sensor thinks 69 > 70). I have a digital display telling me how fast I am, so either my car is lying to me or the device is dead wrong. Or how about when I set the cruise control to 68 and I get to 70 because I'm going downhill.  Yeah, that was totally my fault.

The fuel efficiency is wrong. Sometimes it eats trips. It's maddening.

They don't allow a data export, yet they blog about all this interesting information amassed from the user base. Allow me access to my data, please.

I'd really like to see huge improvements to their algorithms used to determine 'bad driving', data export, and even things to help me shift better (wouldn't that be cool and fuel efficient???).

Ultimately, I've decided to put this device away and *maybe* pull it back out when some HUGE improvements have been made--if I don't sell the sensor first.

UPDATE 3 MAR 2014:
Isn't social media awesome?

There is an alpha developer API for data.  Building some apps around it sound like fun, except I'd like to be able to access the link, as well.  I won't pretend that this will ever happen (and rightly so) but it's fun to wish.

As reported here, the dash speedometer may be a few MPH off from what appears through the ODB link.  My response:

@waynehartman Actually, speedometer dash display can be off by a couple MPH from actual speed. More here: http://t.co/if225gIXj9 ^AM

@automatic OK…since you know that it’s off, why not match the link with what the display shows?

@waynehartman We just take the data directly from the OBD port. But I can check in w/ the engineers about that. ^AM

@automatic Not likely available via OBD, but it would stand to reason with so much aggregate data you have an idea of which cars are off.

I have 'legacy code'.  It has been a few years since an app I wrote first debuted on the App Store, but it all still works.  With iOS 7, I decided to sprinkle in some AutoLayout to bring some parts of the app into the modern era, but ran into some problems and decided after a few commits that I wanted to back out.  I decided to roll the XIB back to it's original pre-iOS 7 self.  Except when I tried to open it, I got this really odd error: 

The document could not be opened. Could not determine the type of data.

At this point Xcode can't determine what kind of document it is, for some reason, and just gives up. I scoured the Internet for a half-hour before it donned on me: Xcode 5 makes updates old XIBs to a new XML structure when they are opened to make them more stream-lined and easier to diff, like storyboards. In order to rollback to the old version it takes a few steps:

  1. DO NOT revert your code first.
  2. Go into the document inspector in Interface Builder and change the "Opens in" attribute to "Xcode 4.6"
  3. Accept the warning that you'll lose iOS 7 capability.
  4. Roll back the changes in git.
  5. Change the "Opens in" attribute back to "Default (5.0)".
  6. Presto-chango: you have now rolled back to the old revision of your XIB and it's now in the new Xcode 5 format.
  7. Commit and push (you don't want to have to do this again, do you?)

I suspect what is happening is that Xcode attempted to parse the old format, thinking it was in the new format, and then gets discombobulated.  Interesting bug and a use case that does not appear to be in a unit test. :)

As an independent app developer I have had an opportunity to learn quite a bit about consumer behavior, how to run a business, and what it means to interact with the end user. When developing a product or service, support is often viewed as a cost center, not a revenue generator. This may seem obvious, but one of the things I have found is that support can actually be used to indirectly generate revenue.

Whether it's bugs, user error, poor interface design, or even enhancements, users seek out help after they have made a purchase. This is a golden opportunity to take what may be a less than ideal experience and turn users into advocates for your product. I have had countless instances where irate users contact me for support of my apps and because of an excellent support experience, end up giving the app favorable reviews, or in some cases, even referring friends and family to make a purchase. In a crowded marketplace, support can be a key differentiator between products.

As you are making decisions on how best to interact with your users, it is important to consider how you can make your support operation scale and align with your goals. Some important considerations might include:

  • How much do you charge for your product or service?
  • What percentage of your users do you expect to seek support and/or give feedback?
  • What expectations do your customers have for support? Conversely, what expectations have you set?
  • What methods of communication will you be willing to allow for users to interact with you?

For example, I have an app, Webmail++, that I sell on the App Store for $2.99. I offer in-app support that generates a standard email template that I have the user fill out. I make it really easy for the user to contact me on this channel. The reason I do this is because the user has paid what they think is a premium amount for an app. I try to respond to these emails within a few hours of receiving them, sometimes minutes.

Many users are very surprised by this for a couple of reasons. First, they are surprised that someone even answered. I am dead serious. People's expectations are that their support requests fall into a black hole somewhere never to be seen again. Their request was just a placebo of sorts to make them feel justified in being upset about a problem they have. Second, the promptness of a response demonstrates that I take seriously the things I do.

Fortunately, I don't have many support requests; support requests/sales per week comes out to be 2%. In this instance, support costs are minimal, but in any case I view support not as a dirty word, but as an opportunity to win over the customer and gain valuable feedback.

One last example involves another app called Trip Receipts. This was an app created over a few days to scratch a particular itch I had. I really embraced 'iterative development' by creating a minimum viable product and getting it into the app store as soon as possible. I created a very bare site and relegated support to a link at the bottom of the page in small font. I sell this app for 99 cents. I knew up front that there were going to be rough edges and things to improve over time, so I wanted to minimize support impact so that I could spend more time refining and quickly making enhancements.

By setting a low price and making the user hunt for support, I am setting expectations that support isn't necessarily going to be 'top drawer'. Interestingly enough, I have still gotten a few support requests, but they were more geared towards enhancements than reporting issues. (As a side note, these were enhancements that were slated for later iterations, anyway.)

In closing, when you're creating a new product or service it is important to consider how you are going to support it. Make sure that you have made some sort of assessment on how you expect to handle support and in turn reinforce those expectations with the end-user. And remember, support doesn't necessarily mean putting a strain on your revenue. It can actually be a means to boost it and your brand.

Despite what other iOS developers might think of Storyboards, I really like being able to use them not only to quickly prototype an app, but to be able to control the flow of a production application.  Today I was building a prototype app and needed to launch a UIImagePickerController and thought about how I might be able to do that via storyboards.  The solution is actually quite simple.

Since UIImagePickerController is a subclass of UINavigationController, it's as easy as dragging a UINavigationController to your storyboard and changing the class identity in the identity inspector of Interface Builder:

identify inpector panel of Xcode

By just add a connecting segue with a unique identifier, you can then programmatically call the segue and then, in the prepareForSegue:sender: method, be able to configure the image picker before it is presented:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
     if ([segue.identifier isEqualToString:SEGUE_CAMERA_PICTURE]) {         
         UIImagePickerController *pickerController = segue.destinationViewController;
         pickerController.delegate = self;
         pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
         pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
         pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear;

Learning how to develop on iPhone/iPad can be a painful experience with a steep learning curve, especially if you're new to Objective-C. There are a lot of tools that Apple provide to help lessen this curve, but sometimes beginners bump into problems that are difficult to solve, if only because the error information is less than informative to the uninitiated. An example of this involves the use of XIBs or Storyboards.

With a drag-n-drop UI, Interface Builder simplifies the creation of application screens and is very attractive to those wanting to hit the ground running on this exciting platform. Having taught intro classes for iOS for a couple years now, I can count on one or two people in each of my classes hitting a major barrier in troubleshooting an app that is crashing: the dreaded NSUnknownKeyException.  You'll get console output that looks something like this:

* Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key play.' * First throw call stack: (0x1c91012 0x10cee7e 0x1d19fb1 0xb7ae41 0xafc5f8 0xafc0e7 0xb26b58 0x230019 0x10e2663 0x1c8c45a 0x22eb1c 0xf37e7 0xf3dc8 0xf3ff8 0xf4232 0x433d5 0x4376f 0x43905 0x8eceab6 0x4c917 0x1096c 0x1194b 0x22cb5 0x23beb 0x15698 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x1117a 0x12ffc 0x222d 0x2155) libc++abi.dylib: terminate called throwing an exception (lldb)

What The Problem Is

At runtime your view controller is going to get deserialized from its XIB/Storyboard. During this process, it's going to read all the objects that are in your IB files and start instantiating them with an NSCoder. As it is instantiating those objects in your view, it's going to read the IBOutlet and IBAction connections in your storyboard and start assigning the hydrated objects to those properties that were connected at design time so that you have programmatic access to them at run time. But here's the kicker: If you have a connection that points to a property that doesn't exist, then this exception will be thrown because it was told a property was there that really isn't.

This problem manifests itself most commonly when a connection is created, but the programmer goes into the header and changes the property name. What's happening is that the runtime is expecting to set a property of a given name on your view controller, but that property no longer exists (because you changed it).

How to Fix It

In your storyboard/XIB, right click on the view controller to view its IB connections:

See how there is a connection for the property 'play' and it has a little yellow triangle next to it? This is Interface Builder trying to warn you that you have a connection set there, but the header isn't showing that there is an IBOutlet of that name.

All you need to do is click that little x to break the connection to the missing property.

Additional Resources:

Key-Value Coding Programming Guide
Archives and Serializations Programming Guide