If You Have Nothing Nice to Develop Then Keep It Out of the App Store

Two of the biggest points that I tried to stress in my presentation, "The Fine Points of iOS Development", are to:
  1. Have a mobile strategy.
  2. Design/Develop your apps with exceptional user interfaces.
It looks like the decision makers at Raycom Media, Inc. did not get the memo.  WMC-TV is a local NBC affiliate here in Memphis, TN.  They tweeted today that their weather app was now available for download.  When I saw it I knew that I would probably not use for everyday use because I prefer the Outside app from Robocat, but I am always interested in what local businesses are doing in the mobile arena.  After using it for 30 seconds I deleted it from my phone. Not because it didn't offer quality information, it was due to the fact that the UI is HORRID.  

Raycom Media, Inc. isn't some podunk little company so I am not sure what their excuse was for letting this travesty out there for people to use and pass it off as something great.  To put it frankly, whoever is in-charge of their "digital" divisions (web and/or mobile) should be fired....immediately. At the very least he/she/they need to take a full day and review the Human Interface Guidelines provide by Apple.  Their websites, desktop and mobile, and iOS apps are cluttered beyond all belief, take forever to load, do not follow web standards and are the aphelion of SEO. Jakob Nielsen would fallout dead if he saw them.

Not to be one that complains without offering suggestions here are a few that would help:
  1. Get rid of that God awful advert at the top of the app. We all get it...you have to generate revenue which is fine, but it's placement distracts from using the app.
  2. Replace the UISegementControls with a UITabBar (make the app UITabBarController based).
  3. Move the "Info" and "Home" buttons which people can hardly see and touch at the moment as tabbaritems.
  4. Remove the scrollview from the map page completely.  It should be it's own "tab".  It has no relevancy in a map context.  You are mixing two different types of displays.
  5. Having custom transitions to a particular days "detail" view is fine, but when you click "Done" and see it again it is just annoying. It is a jarring experience.
  6. The "alerts" button is worthless unless someone opens the app and then happens to click on that button.  Should have option to send out PUSH notifications when necessary alerts become available.
The information you provide is great, but your digital delivery mechanisms leave everything to be desired.

Inspiration from Bill Atkinson

It surprises many people that I talk to who aren't developers when I mention other developers from the "early" days that really inspire me.  Much like how musicians, artists, writers, actors, etc. today will speak of their predecessors who inspired them.

The story that completely changed my thought process on programming and technology in general was that of "Rounded Rects Are Everywhere!".  Today people just assume that technology is easy to create and Adobe Photoshop, Pixar Animation, and Facebook have always existed.  Alas, the trail blazers before us were truly revolutionary and in my case what inspires me are those rounded rects.

The story goes that back in 1981 Bill Atkinson created the functionality in QuickDraw that would draw ovals and circles very quickly.  I know it doesn't seem glamours with technologies like augmented reality and facial recognition, but back then it was way ahead of it's time. Remember, that most processors in '81 didn't have the ability to process floating point values. So the question becomes if you can't use square roots (resulting in floating point values) how to do the necessary calculations. Multiplication/division…yea I guess you could, but the 68000 processor was still pretty slow at that.  Bill figured out a way to do it with just addition and subtraction.

"Bill's technique used the fact the sum of a sequence of odd numbers is always the next perfect square (For example, 1 + 3 = 4, 1 + 3 + 5 = 9, 1 + 3 + 5 + 7 = 16, etc). So he could figure out when to bump the dependent coordinate value by iterating in a loop until a threshold was exceeded. This allowed QuickDraw to draw ovals very quickly."

As excited as Bill was and demoed this to Steve Jobs, he was posed the question about making rounded rects.  Bill tried to dismiss the idea as a waste of time, but Steve showed him how prevalent rounded rects are in everyday life.  Later that afternoon Bill returned with the solution.  As such rounded rects have since become indispensable.

What I take away from this story and why it inspires me so much is Bill didn't throw his hands up when faced with a programming limitations, but thought outside the box and used a very straightforward solution to solve a seemingly complex problem.  The second aspect that I take away is to be inspired by what is around us and that we use everyday and to incorporate that into application design.

Custom Navigation Transition for the iPad - Coming Soon

For the past month I have been working on a personal iOS component after seeing and being inspired by a custom UI transition in an iPad app that I downloaded recently.  

Since then I have been trying to reverse engineer it with some tweaks here and there.  The goal was to be able to license it out for others to use, but the more that I thought about it I just can't justify charging for it.  It it turns out the way that I want to I feel, and hope, that more devs can benefit from it by including it in their apps so I will open source it on github.

I have some more work to do before I post even an "alpha" preview, but I am hoping within in the next few weeks it will be ready for people to comment on and possibly improve.

Ordered Results using DirectoryIterator

No matter if you are beginner or expert one of the most command tasks that you  will do is writing some class/script/snippet of directory iteration.

"Get a list of files/directories and display"

With PHP there are about baker's dozen different ways of accomplishing this.  In the beginning there was functional verbose way:

It gets the job done, but not very extensive and it seems VERY verbose.  Being that my development background started with OOP I was never a fan.  Fastforward a little bit and PHP introduced "dir", which returns an instance of the Directory class.

Not to bad, but still verbose and God forbid that you have to do recursion.

With PHP5 came the SPL. Standard PHP Library, which still to this day I don't know why it isn't prompted more. Pure object-oriented and has the flexibility to accomplish the basic tasks set before them, as well as, the strength to be a customizable as the developer wants.

The class which most use for directory iteration is…hold your breathe: DirectoryIterator.  In my use case I need to server up image path and meta information in an HTTP request so that an iPhone app could parse the response and grab the appropriate images for display.

Basic usage:

See how easy that was.  OOP at it's best except for one little thing.  The images were not coming back in the correct order.  They are named on the filesystem: "00.png", "01.png", "02.png", etc., but the return was random.  While I can appreciate DirectoryIterator being a more "abstract" enumator and not really having a "natural" sort order I still was frustrated.  Remember, what I said earlier though about the SPL being customizable and OO.  You can subclass the DirectoryIterator and supply your own comparator, which by design, is best practice for a large system.  I, however, was looking  for the shortest line between two points and creating a subclass seemed overkill.

*I really wish PHP had categories like Objective-C or method swizzling

Not a problem though.  I can just pass a callback function to the usort function and call it a day.  H.O.P.  This logic does work, but the array that I wanted to sort is associative so the key that should be sorted is "name". The callback function for usort ONLY accepts two arguments which it compares.  I had to bake in the key which isn't flexible.  I would rather reuse the functionality by being able to pass in the key to sort on. PHP isn't the only language that has this result.  If you look at the behavior of an NS(Mutable)Dictionary in objective-c which makes copies of keys, so the objects in the key array will be different. Objective-C offers the ability to pass in a comparator when iterating over the dictionary so that the sort order is defined by the developer not by the hash.

In a perfect world I would be able to do the following:

Here is the example script for my use case. (changed some path names for security reasons)

JandB Photo App 2.0 - Coming Soon

After a few months of work the JandB Photo App version 2.0 is almost ready for App Store submission.  The main goal for this release was the ability for users to download the galleries locally to their phone for offline viewing and smoother transitions. I also made some subtle UI changes that I think make the app look a little more polished.

I wasn't able to add in native 4.x support due to my timeline and external library dependencies. Mainly, the Google objective-c library, Facebook's SDK and the Three20 library.  So many changes, good one's by the way, have been made to them that I am going to have to do a lot of refactoring.  Rest assured that those enhancements are the next to come. In addition for users to have the ability to add comments to a photo when posting it to Facebook and saving a photo as their phone's wallpaper.

If you haven't downloaded it already head over to the App Store and check it out.

Version 2.0 is coming soon...

Custom UIActionSheet Using Core Animation

About four months I posted a blog and project that showed how to customize the buttons of a UIActionSheet.  In the disclaimer I stated that because of the use of the private api's if you attempted to submit your app with this technique to the App Store it will get rejected.

This time around a created a simple, yet effective customized, mock UIActionSheet.  Essentially it is just a custom UIView with three buttons that animates and dismisses just let an UIActionSheet.  All you have to do is assign a method to each of the buttons.

If I have time then I'll try and make it even more extensible by creating a custom delegate to make the classes even more reusable.

Name Management with ABAddressBook and NSString Arrays

A few days before New Year's Eve my wife asked me if it would be possible to create a simple iPhone app that she could feature in an upcoming presentation for one of her company's clients.  Being the awesome husband that I am I said "No problem!". I had about 5 days.

While most of you were gearing up to celebrate the New Year I was spent most of the day finishing up the majority of the app.  One of the basic features that I added in was the ability to add an employee to the user's addressbook.  Not the most exciting feature in the world, but one that people always want.

The small hurdle that I ran into was that each employee's name wasn't split into first/last, but all on one line.  The most efficient way to handle that is assume that the first word is the first name and everything else is the last.  Granted, I am assuming a lot, but 95% of the people in this scenario only had two names: first and last.

Below is the code I used.  Once again, not the most glamourous piece of Objective-C, but effective.

Objective-C Objects Are Not Always Created Equal or Identitical

Update:

Take a look at Mattt Thompson's amazing article, and much more in-depth, article about this topic.

In my latest project I have to validate two custom objects by comparing them for their equality.  Most languages have a few techniques for accomplishing this task.

PHP - == and ===:

"When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class. On the other hand, when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class."

Java==, .equals(), compareTo(), and compare():

"==" - Comparing to see if a reference is null. Comparing two enum values. This works because there is only one object for each enum constant. You want to know if two references are to the same object

"a.equals(b)" - Compares values for equality. Because this method is defined in the Object class, from which all other classes are derived, it's automatically defined for every class. However, it doesn't perform an intelligent comparison for most classes unless the class overrides it. It has been defined in a meaningful way for most Java core classes. If it's not defined for a (user) class, it behaves the same as ==. It turns out that defining equals() isn't trivial; in fact it's moderately hard to get it right, especially in the case of subclasses. The best treatment of the issues is in Horstmann's Core Java.

"a.compareTo(b)" - Comparable interface. Compares values and returns an int which tells if the values compare less than, equal, or greater than. If your class objects have a natural order, implement the Comparable<T> interface and define this method. All Java classes that have a natural ordering implement this (String, Double, BigInteger, ...).

"compare(a, b)" - Comparator interface. Compares values of two objects. This is implemented as part of the Comparator<T> interface, and the typical use is to define one or more small utility classes that implement this, to pass to methods such as sort() or for use by sorting data structures such as TreeMap and TreeSet.

Objective-C

"A common tripup for programmers moving from other languages to Objective-C is dealing with the difference between equality and identity." - http://bit.ly/hC5BlJ

That statement couldn't have been closer to the truth.  Objective-C provides, like other languages, similar techniques for testing the equality and identity of objects.  You can use "==", "isEqual", and "isEqualTo".  While I won't go into the gory geeky details of the differences because this site does a ROCK SOLID job of doing that I will point out some gotchas and what I would consider best practices when implementing this feature.  Please note that if you want compare two different objects correctly then you custom classes, subclasses of NSObject, MUST implement/override isEqual and hash.

Here is the basic example to start out with in your object:

Doesn't seem too difficult does it?!  What I didn't pay attention to at the time was that my class contained properties that were primitive and thus trying to "hash" those values caused compiler error's.  In addition, when taking the hash of multiple properties it is more efficient to concatenate the result with XOR (^) as opposed to "+=".  Please note that this will NOT prevent you from having 100% accuracy.  For example, you could hash, "Cory Wiles" and "Wiles Cory"....they will end up having the same hash, but they don't have the same identity.  For my use case I don't have the need for a custom hash algorithm, but it is something to keep in mind when you are architecting your own classes.

The other area that I found myself banging my head against was that my implementation of isEqual kept failing for a property of another objective.  Just so happens that the other object was an enum value so I had to treat as an int.  Once I re-factored everything worked as expected.

Simple "hello example" snippet:

In summary, no matter what language that you use, IMHO, comparing objects is more than calling "==" and should NEVER be an after thought. If that is your mindset then you a) should quite programming immediately  and/or b) except HUGE headaches in the new future. There is a linear increase in complexity of your hash algorithm compared with the complexity of your class properties (primitive types, custom objects, NSArrays, NSDictionary, etc). 

Universal iOS App Template with TabbarController Support

I updated the iOS Universal App to now include TabBarController support.  At this point it is very a simple implementation and the tabbar item have to be built programmatically, but there is lots of flexibility in any implementation.  Let me know if anyone runs across any bugs and/or improvements.  By the end of next week I should have another branch created with iAd and TabBarController support.