I Will Not Ride the Dell Lightning

Being that my passion for development and design are usually centered around mobile apps I am always interested in any new platforms and handsets that poised to make any impact on the current market.  As such I was really interested in the article posted over at Engadget yesterday: Dell Lightning: the ultimate Windows Phone 7 device leaks out. However, my enthusiasm faded after the first sentence and twindled down to zero by the end of the first paragraph.

"Hot damn, people. The mother of all Dell leaks just dropped into our laps, and the absolute highlight has to be the Lightning, a Windows Phone 7 portrait slider."

I can overlook the fact that the device is running Windows and some of the on screen usability issues because I haven't used one, but what bothers me the most is that handset manufactures can't seem to understand handset design.  This phone is presented as having a "revolutionary" device design, but once again you have the same tired, inefficient slide-the-handset to show the qwerty keyboard.  Really?! That is the best you have. That is NO different from all the other handset designs that are offered by ever manufacturer in the world for the past 5 - 10 years.  Dell and Microsoft combined have more money than most European countries.  Why they don't or can't find/recruit/steal the BEST designers and developers to come out with a real competitor to the iPhone is beyond me?  However, what this does mean that within 6 months of this device launching you will see it sitting next to the Dell MP3 player that was supposed to be so great.

Looking over some of the other features that the device offers, once again there is nothing that I can't get, and probably better, with an iPhone or Nexus One.

::NOTE::

When I was attempting to find a link to the dell jukebox from their website it didn't come up.

To Kill A Mocking Bird Called "Your Twitter App"

Over the past week there has been quite a bit of news coming out of the Twitter HQ. First it was announced that Twitter has acquired Tweetie and subsequently hired it's author Loren Brichter.  They also have launched the promoted tweet service and for you real bird watchers out there the ability to add meta data to tweets using the API.  Finally, it was confirmed that Twitter is going to launch their own URL shortener and stop using bit.ly.  A recently published article on Mashable summaries one tech startup's frustration with the announcement of Twitter now coming out with it's own "official" Twitter client. Why is there so much frustration? Because developers, at times, feel they have been sabotaged by the very companies they are using.  Just to be clear, they are upset because a service that Twitter owns, that they allow developers to use for free, is now being used by the very company that created it in the first place to promote their own brand!

I'm just saying...

I am developer and know what it is like to have that great idea or great app and to have some MUCH bigger/better company come along and launch their own version which inevitably kills mine before it got off the ground.  However, those are the ropes.  Don't put all your "1"'s and "0"'s into one app or service.  That goes for everything in life.  This animosity towards Twitter, and any other information service, is quite misdirected.  As mentioned earlier, Twitter didn't go out and build their own app, they chose, quite possible the best Twitter client in the AppStore today.  Did developers really expect Twitter to NOT have an official app.  I am surprised it has taken them this long.  That is like Apple releasing the iPod, but not iTunes.

What does that really mean? If you create something that is TRULY great then there is a good possibility that it will get picked up.  Just look at all the startups and other mashups that have been acquired by big companies lately. Twitter has just released a site for developers that will aid the creation of new mashups and services to use with the information they provide not hinder innovation.

It is an unfortunate price that one has to pay when the service you rely on for your mashup comes out with their own official app that does the same thing and my sympathies are definitely with you, but if all you do is rely on that ONE great idea then you weren't going to last that long anyway.

Creating Custom Glossy Gradient Buttons Programmatically

As my experience, and hopefully skill, in iPhone development has matured over the past year and half I am in the constant search for the best techniques for my apps to run better, faster, and consequently more efficient.  Of the top developers that I follow they all make references to the importance of utilizing subclasses of UIViews and the underlying subsets of views in general.

I love the UI elements that are used on the phone. I didn't realize the awesome power of CoreAnimation and the flexibility that it gives you to manipulate and create graphics as such a granular level.  I set out to see if I could recreate a common iPhone UI element completely programmatically: a glossy gradient button that still responds to touch events.

The end result was a success and a great learning experience.  I still need to add in more testing to make sure that interacting with all these views is more efficient than interacting with standard pngs.

This biggest issue that I ran into was "re-enable" the button actions.

Simply subclassing UIButton did create a problem when dealing with the UIControlEventTouchUpInside/UIControlEventTouchUpOutside methods that you associate with buttons.

I was able to overcome this issue by implementing the touchesBegan and touchesEnded methods.  Remember...UIButton inherits from UIControl, which in-turn inherits from UIView.

Problem solved.

Download Project

Turn by Turn Directions with MapKit and Google Maps

Update - 03.31.2010

I decided that I didn't like the accuracy of the location from the browser.  It is isn't as good as the MapKit or default Google Maps app on the phone.  I added a button the directions page to open default maps application.

One of the best features used in Google Maps is the turn-by-turn directions.  Unfortunately, I haven't seen, and don't even know if it exists without proprietary code, an effective way to show turn-by-turn directions using the MapKit API in the iPhone SDK.  Though Google announced that they have included it in their Android platform they were vague about if/when it might come to the iPhone SDK.  No matter, where there is CoreLocation there is a way.

Goal
Most smaller companies only have one "brick and mortar" location.  So I wanted to show that location on the map and then present the user with ability to get turn by turn directions to their location.  In my example app the marker will show the location of my favorite sushi place in Memphis, Sekisui's Pacific Rim.

Obstacles
No clear way to implement turn-by-turn directions with MapKit using the iPhone SDK.  Though Safari for the iPhone has the ability to get your current location via the browser, i wasn't very impressed with it's accuracy.

Solution
Use CoreLocation to get the user's lat/long and then pass that to a UIWebView that will display a Google Map with directions.  Though in this example I am using a local html that is stored on the phone a better implementation would be to have the file stored remotely and then cached on the user's phone for faster load time.  However, it is important to note that you should "decache" the file if the user's previous coordinates are different then their new current location.

Note
For the best results and accuracy it is better to run this on your device since CoreLocation the simulate will show Apple's headquarters as the user's location.

UIViews with Rounded Corners and Animations

One of the best iPhone reference books on the market today is iPhone SDK Development by Bill Dudney and Chris Adamson, published by Pragmatic Programmers.  The examples are real-world, easy to follow and cover just about any area of development that one needs.  In my earlier projects and example code I tended to use a lot of graphics for buttons and backgrounds because I need something with rounded corners and/or a gradient.  However, in my latest project I have wanted to get away from that and utilize CoreAnimation and more UIView drawing techniques and the results have been outstanding.  Load time on my views are much faster because all the drawing and rendering are done on the compiled view level and not from the rendering of an image.

 I created a sample project that loads a three different views onto the controller and animates them.  There is nothing overly complex about the code at all and can be customized to be more configurable, but is written to show the power and flexibility of creating custom views and animations.

::NOTE::
The rounded corner drawing in the project was sample code from the iPhone SDK Development Book.  Credit where  credit is due to Bill and Chris.

As always I encourage anyone who downloads the project to make any modifications and/or enhancements.  For example, you could add in the functionality of firing of the animation based upon text field values or randomizing the speed of the animation.

Displaying Data on the iPhone with Index UITableView

It is forgone conclusion that if you need to present a large amount of data with a UITableView then you should do so using an index and index sections.  As with most tutorials that I have read on this topic, the scenarios used got me 80% of the way.  In my humble opinion, the solutions where either over engineered or they didn't apply to my use case.  Hopefully this tutorial/sample project will bridge the gap.

The tutorial that I got the most from is: iPhone Development: Creating Native Contacts like screen.

One of the biggest hurdles that I had to over come, that was different from the contacts tutorial, was that I wasn't using a database and therefore didn't have a predefined sub-result set for each character.  I was having to do the opposite.  I had to iterate over my result set, array of states, grab the first letter from each item, check to see if there was already a dictionary key that existed for that letter and proceed accordingly.

Logic Flow
Iterate over states
Get the first letter of that particular state
Check to see if there is a key in the objectsForCharacter dictionary
   - YES: add the state string to the arrayOfNames array and then set the arrayOfNames to the objectsForCharacter dictionary for the appropriate key
  -  NO: remove all objects from the arrayOfNames array and add the firstLetter to the arrayOfCharacters.  Then proceed on to the above "YES" steps
Once all the states have been "proceed" then reload the table data

Final Model
Though it sounds some what complicated with all the arrays, dictionarys, etc. once you break it down to a visual model then the code is easier to comprehend.

[[objectsForCharacters objectForKey:@"A"] objectAtIndex:0]; // Alabama
[[objectsForCharacters objectForKey:@"A"] objectAtIndex:1]; // Alaska
[[objectsForCharacters objectForKey:@"A"] objectAtIndex:2]; // Arizona
[[objectsForCharacters objectForKey:@"A"] objectAtIndex:3]; // Arkansas

Download Example Project (comments/enhancements are welcomed)
IndexedTable.zip

EraseUrX: The Story of My App

Not My Idea
Erin always asks me if I use one-third of the apps on my iPhone.  Truthfully I don't.  There are probably four apps that I use 80% of the time. The others I download or purchase because they inspire me. I might like the way that the app is designed or handles a particular usability feature or the combination.  Then there are the few that I downloaded because my daughter REALLY likes them.

The three or four ideas that I had for my first "App Store" app where good, but they would take quite a bit of time to develop and I was looking for a project that would be  straightforward that people could use and that I could turn around in about two or three months working on it part-time.  My wife came up with a fun concept of having an app that would allow a user to "erase" their ex from their phone.  Immediately, I thought this was a great idea and  the brainstorming began.

Early Stages
As a developer I knew what I wanted to put into the app, as far as, functionality goes, but I really wanted my wife's thoughts/opinions/feedback since she:

1. Came up with the idea
2. Is in sales/marketing and knows "people" better than myself

In the beginning she started the conversation with, "Can the phone do this?".  I stopped that immediately because I wanted to hear what she envisioned as the perfect break-up app.  After getting a list of all the "wants" we sat down together again to go through them and make our first round of cuts which basically amounted to me explaining that the phone didn't have that functionality.  Over the next few days we came together again and made a list of three or four major features that needed to be included with some "nice-to-haves" added at the end.  Let the coding fury begin.

Hard Decisions
As I started down the path of coding the app things went VERY smoothly and I was quite happy with my progress and my continued growth of knowledge of not only Objective-C/CocoaTouch, but mobile usability as well.  When I got about three-fourths of the way done with the project I hit a fork in the road.  I came up with a handful of features that I thought would be GREAT to add into the application, but would extend the project at least 4 weeks.  The features included various Facebook integrations, a "breakup/erase wall", video recordings (for those 3GS users), canned messages, top 10 breakup songs from iTunes, etc.  However, I had to make the tough decision to keep the current feature list and mark it as version 1.0 and save the others for future releases.   I am working currently working on version 2.0.

What Made the Cut?
The simplicity of the app is what, IMHO, makes the app pretty good.  I decided to keep, what I considered, core functionality.  The ability to send a photo and/or an audio recording and/or a written message via email.  I did add in the persistence level of the data and the ability to create multiple audio files, as well as, manage those files.

In Apple's Hands
Finally, after months of development, in the wee hours before work and after my daughter went to bed, I incorporated the custom UI elements, create a product site, and submitted EraseUrX to the App Store.  Fingers crossed.

Release

Seventy-two hours later, I got an email from Apple saying that app had been approved and was for sale in the App Store.  Like a kid at Christmas I couldn't click on the link fast enough.  To my dismay I got the equivalent of a 404 error.  I wish they would have had a little note in the email saying that it might take up to X amount of hours for the app to propagate to all their servers.  None the less by the afternoon it was there.  I had successfully planned, created, designed, and deployed an app to the App Store.

Hindsight
Looking at the complete process I do not have too many regrets.  The things that I would do differently are as follows, and in no particular order:

1. Start the marketing for the app earlier than right after I submitted the app.
2. I should have kept a development "diary" online that showed the progress and little teasers.
3. Had a promo video that went along with the app.  Not a technical video of what the app does, but a marketing video.
4. Done more research on successful, and maybe, unconventional ways of marketing the app.

What's Next
While I don't think that EraseUrX is a revolutionary app, I do think that it is decent, but like any creation it can, should and WILL be improved. There will be the option to either send the "breakup" via email or to Facebook, more fine grained control over what is saved on your phone for later review, video support, and a cleaner design.  As stated in my previous entry, the completion of this project has just fueled my desire to work more exclusively on iPhone apps.  Some will be personal projects, but for right now I'll concentrate on contract projects.  I am currently working with a local photographer to create an app to showcase the work that he does.  It is more than just another photo gallery slide show application and I think will have some nice additions to what people normally expect.

Stay tuned...

The Drive to Build More

Based upon the myriad of tweets over the past three months or so, most who follow me know that I have been working on my first iPhone app.  Well, first to submitted to the app store.  I have finished an app for work and have started on another for www.feedfootball.com.  Though the app hasn't hit the stores YET, I already have the inspiration to build more.  EraseUrX has by far been the most rewarding project I have worked on in the past three years.  Even if I don't make a lot of money, it truly has been self satisfying to just complete this project.  I can't wait to get started on the next one not only for the challenges that await, but also I know that I be able to put it in the App Store faster.

There has been a lot of criticism of Apple's approval process in the App Store, but over the past three months they have made great strides to improve this process and it has benefited developers greatly.  In addition, there are rumors floating around of a possible upcoming announcement of the 4.0SDK and a new phone device, which if the 3.0 release is any indication of the amount new features added to the phone, then the 4.0 release will give developers even more tools to increase the usability and features in our apps.

Hopefully, the saying is true...

If you build it they will come.

2010: Location, Location, Location

I guess you could really argue that the "mobile revolution" was started when Apple first released the iPhone, but 2010, I predict, will be a year full of explosive new mobile technologies and adoption.  2009 saw a huge spike in the adoption of smart phones, as well as, the release of new platforms, devices, and applications.  For the past 10 years I have focused on desktop web apps, but am VERY excited about the breakthroughs and innovation that has evolved in the mobile arena, especially with the offerings coming from Google and of course Apple.  As a consequence, 80% of my focus will be on mobile applications, both native and web.

2008 was the year of "web 2.0", 2009 was consumed by social media, and I predict that 2010 will be a digital Magellan on steroids with the Location Based Services popping up everywhere.  Evidence of this is already presenting itself, with the purchase of GeoAPI from Twitter, Google is offering "turn-by-turn" directions for free in the latest Android SDK, and Apple purchased a map tile software company.  The question will be how will all this data and the services used to manage the data be best served for the consumer.  The days of showing pins on a map are growing quite old.  It is time for more forward thinking, which is what the before mentioned companies do best.

AVAudioRecorder prepareToRecord Silent Error

I was working on the voice record feature for one of my upcoming iPhone apps, but when I would try to start recording the app would crash.  During the adventure of debugging I couldn't trace anything back to my code as far as memory leaks, uninitialized properties, missing delegate methods, etc.  After about an hour I think I almost as many NSLog entries as I did code.  The two biggest troubling aspects where:
  1. prepareToRecord was the method that was failing
  2. AVAudioRecorder initialization wasn't throwing any errors
I turned to some sample code that I knew worked, but mine would still fail.  At this point I knew it was going to be something little that I was overlooking.  After reading through a few posts on StackOverFlow I noticed a difference in my audio configuration settings that was being passed to: initWithURL:settings:error:

I have a separate class where I set the settings argument.  The last two setting items are for: AVLinearPCMIsBigEndianKey and AVLinearPCMIsFloatKey.  Their values need to be NSNumbers so I was using [NSNumber numberWithBool:], but instead of passing in "YES" or "NO" I was passing in TRUE and FALSE, which is INCORRECT.  Just one of those oversights I forget about when switching from one language to another.

I am still not sure why my NSError wasn't populated with some information.  I don't know why the initializer didn't catch my syntax error either.

After I made my corrections, the recording worked perfectly.  Whew!  Now I just need to write the playback portion.