Will Code For Fun

Filed in 360iDev, iDevBlogADay, iOS Development | Comments (2) |

My work is fun.

It usually is challenging and non-trivial, but it is also fun.

My clients find the results valuable, but it is still fun.

I attended 360iDev this week which was great fun — but it is not why my work is fun.

Working with smart and creative people is fun — but they are not really why my work is fun either.

My work is:

  • Long hours of head down struggles with conflicting demands and confusing requirements;
  • Opportunities and possibilities rattling around my head for days;
  • Researching problems and fixing them cleanly;
  • Struggling with multiple design iterations to find what works best;
  • Discovering what will best meet people’s needs;

I’ll be honest, not every day is fun, nor is every task, but almost every one could be. I’d like to explore what it takes to turn the drudgery into fun, and move from just slogging through tasks to actual enjoyment.

What is “Fun”, Anyway

In A Theory of Fun, Ralph Koster says:

fun is the act of mastering a problem mentally.

My work certainly has problems that can only be solved with the mind, and successful work definitely includes mastery. So, by Koster’s definition, it is possible for my work to be fun.

Jesse Schell says in The Art of Game Design that:

fun is pleasure with surprises.

Well, my work often has surprises, but they do not all bring pleasure. But, his definition seems to have enough room in it to say that my work can be fun.

I Recognize “Not Fun” When I See It

But what about work that seems *not fun* by any reasonable definition. What is it that takes those problems, mental challenges, and surprises and transforms them into fun? The process that Schell uses to define game has helped me understand what that transformation of work from “not fun” to “fun” might require.

He builds a definition for “game” by investigating what others say about fun, play, and other terms which made me think about what makes my work fun. Key among those terms is play, which he defines as “manipulation that satisfies curiosity”. The bulk of my work is manipulating things like ideas and algorithms, so this seemed like an interesting place to start.

Is It “Work vs. Play” or “Work and Play”

I manipulate things in my work, but what about satisfying curiosity? And what about fun?

Notice that Schell’s definition of play does not require it to be fun — you can play with something that turns out not to be fun. That seems to be close to work — you can work with something that turns out not to be fun. Since my desire is to make my work fun where I can, I think looking at play a little more might be helpful.

He quotes George Santayana on play:

Play is whatever is done spontaneously and for its own sake.

When I think of work, spontaneity does not leap to mind. But when I am free to choose projects and clients, there can be a spontaneous feel to it, and it definitely includes a “for its own sake” component. When I have control over what I work on, I will choose the more interesting work — work where I can learn, grow, and satisfy my curiosity about something. So the more freedom I have in choosing projects and clients, the more fun my work will be.

This leads to my first tip about making my work fun.

Tip #1 — Do not let current constraints on your work immobilize you, they should motivate you to find ways to have more control over your work.

Attitude Is King

But, there are always some tasks we must do that do not really appeal to us. Schell expands on “for its own sake” with examples and observes “an activity itself cannot be classified as a ‘work activity’ or ‘play activity’. Instead, what matters is one’s attitude about the activity”. This leads to another tip:

Tip #2 — While you cannot always choose work activities, you can always choose your attitude.

Schell combines several concepts and concisely defines a game as “a problem-solving activity, approached with a playful attitude”. I believe this applies directly to my work. Even unpleasant tasks can be made more palatable, and perhaps even fun, with the right attitude.

Adjusting My Attitude — The Key To Making Work Fun

Fresh Eyes

Two young developers I met this week at 360iDev illustrate how work can be fun. Santiago and Charlie, somewhere around 13 years old, are friends who share a love for making their iPhones do cool things. I won’t pretend to know them well enough to understand all their motives, but they were most definitely having great fun. They were right there in the front in most sessions, even participating in the 360iDev Game Jam until about 2am. It was a joy to watch them.

Watching them during the Game Jam leads to another tip:

Tip #3 –Look with wonder at the cool things that are possible.

(They both have several apps in the store. If you are interested check out Santiago’s Apps and Charlie’s Apps.)

Thankfulness

I am very blessed to be able play around with such cool and powerful stuff, which leads to the last tip:

Tip #4 — Remember to be thankful for the opportunity to attempt great things, whether or not you end up making a living from it.

My Work Is Fun, Yours Can Be Too

How fun is your work? If the answer is “not very”, remember these things:

  1. Find ways to have more control over your work,
  2. Choose your attitude towards your work,
  3. Look at your work with wonder at the possibilities,
  4. Remind yourself to be thankful that you can play with such cool stuff.

As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation. A great collection of indie iOS developers have helped me stay on track, developers from local user groups, those associated with iDevBlogADay, or those I have met through 360iDev. I encourage you to find local NSCoder nights, developer meetup groups, or other user groups to keep your motivation on track. If there aren’t any meeting locally, try to find just one other local developer and start one.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

My Growing iOS Developer Toolbox — Logging With Levels and Categories

Filed in iDevBlogADay, iOS Development | Comments (2) |

I really love working with iOS and Objective-C, but I still feel like I am missing some items from my developer’s toolbox. (I am using the term ‘tool’ generically to cover anything from a fairly simple development pattern to a full fledged application.) Those missing items fall into several categories:

  1. Existing features within Xcode or other Apple tools that I have not yet found;
  2. Tools that are not needed within this new environment that I only think I need;
  3. Tools that have no direct one-to-one replacement;
  4. Tools that have some third party support that I have not yet found;
  5. Useful tools that really do not exist yet in the Objective-C world.

I usually learn a new language itself much faster than I get comfortable with the new environment, development style, and available tools. So, when I feel like something is missing, I know it might just be part of the learning curve. When I move to a new platform, I want to be willing to think differently and adapt to it rather than fight it — the difficulty is often deciding which category that missing piece falls in.

A Tool Missing From My Objective-C and iOS Development Toolbox

One of the the simple tools I use heavily during development in Java is Apache Commons Logging and Log4J. For those unfamiliar with the Java world, they are simple packages that allow you to easily manage development and production logging. They support multiple categories and multiple levels within each category, and are easily configured at runtime via a simple text file. For the majority of applications, you can leave the logging in place and just disable it in the configuration file with a negligible impact on performance. It is great to be able to come back to existing code to make changes and simply enable detail level logging for individual categories (usually based on class name) to more easily monitor what is happening.

When I first started heavily into iOS and Objective-C last winter, I went searching for replacement tools in several areas, including this one. I did not find a one-to-one replacement, mostly because of the difference in the development environment, but I still had a desire for something close. My searching found several people doing limited forms of this via custom macros to wrap NSLog statements. I like to credit those on whose worked I build, but I did not track the source of most of what I learned and it has been too long for me to remember. So feel free to use what you find here however you wish, knowing that much of it did not originate with me.

Requirements for Objective-C Logging

I have no desire to implement an entire framework to support logging, nor do I want to duplicate everything from the java packages, even though there are lots of useful things I am ignoring.

My simple requirements are:

  1. Control logging horizontally via debug levels;
  2. Control logging vertically via categories;
  3. Enable or disable logging via very simple changes;

Debug levels are important to me because usually I want only higher level log messages displayed to avoid unnecessary detail in the console log across all of my classes.

Categories are important to me because when I am focused on a particular subsection of code, or an individual class, I want to be able quickly disable logging at any level for all other categories. This allows me to more quickly find the pertinent messages and finish my task, whether it is debugging or implementing a new feature.

It is also important to me to not add configuration complexity to my project (Xcode has enough of that), so I wanted to have only one or two places where I could tweak the levels and categories.

Macros for Objective-C Logging

I reuse IGDebug.h across projects, so it does not contain any project specific definitions. For convenience, I include this file in my precompiled header.

I enable debug logging for a particular target by setting the value of Preprocessor Macro to IGDEBUG_MODE=1 in its configuration for the debug Distribution. By setting this only for your Debug distributions, you can ensure none of the debug logging is included in your release distributions.

My project specific categories are defined in a separate, project specific header file. I recommend placing the category defines in a single file, it makes it easy to find them, but the IGDebug macros do not care where you define your category.

IGDebug.h

/*
 *  Created by Douglas Sjoquist.
 *  Copyright 2010.
 *  Free to use or modify for any purpose.
 */

// Define IG_DEBUG_MODE for Debug distributions in project build config files

// if IG_DEBUG_MODE is set, then these macros are in effect, otherwise they do nothing
//   IGDStatement includes enclosed text as a statement, only simple statements will work
//      (intent is to used when a temporary object needs to be created to display in subsequent log message)
//
//   IGDLog takes 3 or more parameters
//      l   --  debug level, an integer value that is compared against the value of
//              IGDBG_MAX_LOG_LEVEL to determine how detailed of log messages should be displayed
//      c   --  additional condition that must be true to display log message
//              the intent is to allow specific classes to be turned on and off via individual
//				#defines, but it can be used for any purpose whatsoever
//      s   --  NSLog format string to use
//      ...     Var args that match the format string
//
// IGALog displays similar log messages, but is unconditional (no debug level, conditions, and ignores IG_DEBUG_MODE)
//
// IGDSLog and IGASLog behave the same, except they include the self pointer as well
// IGDFLog and IGAFLog behave the same, except they include the filename/linenumber as well
// IGDSFLog and IGASFLog behave the same, except they include the self pointer and filename/linenumber as well

#define IGDBG_TRACE 3
#define IGDBG_DEBUG 2
#define IGDBG_INFO 1
#define IGDBG_WARN 0

#define IGDBG_MAX_LOG_LEVEL IGDBG_INFO

#ifdef IG_DEBUG_MODE
#define IGDStatement( s ) s
#define IGDLog( l, c, s, ... ) if (((l) <= IGDBG_MAX_LOG_LEVEL) && (c)) NSLog( @"%@", [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGDSLog( l, c, s, ... ) if (((l) <= IGDBG_MAX_LOG_LEVEL) && (c)) NSLog( @"<%p> %@", self, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGDFLog( l, c, s, ... ) if (((l) <= IGDBG_MAX_LOG_LEVEL) && (c)) NSLog( @"%@:(%d) %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGDSFLog( l, c, s, ... ) if (((l) <= IGDBG_MAX_LOG_LEVEL) && (c)) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define IGDStatement( s )
#define IGDLog( l, c, s, ... )
#define IGDSLog( l, c, s, ... )
#define IGDFLog( l, c, s, ... )
#define IGDSFLog( l, c, s, ... )
#endif

#define IGALog( s, ... ) NSLog( @"%@", [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGASLog( s, ... ) NSLog( @"<%p> %@", self, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGAFLog( s, ... ) NSLog( @"%@:(%d) %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define IGASFLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )

Using IGDebug.h

The examples shown below include IGConstants.h, a project specific file I use to configure all my logging categories in a single place. There is no magic to it, it is just a list of #define statements to define the adhoc logging categories I use.

There are two types of macros defined in IGDebug.h: logging macros intended for use in debug distributions only, and macros that should produce log output in all distributions. The debug versions are prefixed with “IGD” and the always log versions are prefixed with “IGA”. There are four different macros in each set:

  1. IG?Log — functions as a simple wrapper for NSLog, adds no extra output
  2. IG?SLog — adds the self pointer to the log output using <%p>
  3. IG?FLog — adds the file name and line number to the log output
  4. IG?SFLog — adds the self pointer, the file name, and line number to the log output

The debug versions of these macros also include two additional parameters to control the logging level and assign it to a category. The logging level parameter should be an integer, and will be compared to the IGDBG_MAX_LOG_LEVEL definition defined in IGDebug.h. The category can be any value that evaluates to true or false — in my exmaples I use simple #define values of 1 or 0 to enable or disable log output for that category.

Example usage

IGConstants.h

#define GESTURE 1
#define SUBGESTURE 1
#define TOUCHINFO 1

IGTouchInfo.m

- (IGTimeAndPosition *) addCurrentTimeAndPositionInView:(UIView *) view {
    IGTimeAndPosition *timeAndPosition = [[IGTimeAndPosition alloc] initWithTime:[NSDate timeIntervalSinceReferenceDate] position:[touch locationInView:view]];
    IGDSFLog(IGDBG_DEBUG, TOUCHINFO, @"createCTAP: %@(rc=%u)", timeAndPosition, [timeAndPosition retainCount]);
    [timeAndPositionArray addObject:timeAndPosition];
    [timeAndPosition release];
    return timeAndPosition;
}

Caveats

Because these are macros, you may find cases where values you want to display confuse the preprocessor. As a workaround, I added a IGDStatement macro that simply wraps an existing single Objective-C statement. The intent is to be able to calculate a value to use in a logging statement that is only included when IG_DEBUG_MODE is defined.

Example usage of IGDStatement

...
    CGFloat movementRange = [touchInfo movementRange];
    NSTimeInterval timeDiff = [touchInfo timeDifference];
    IGDStatement(CGPoint min = [touchInfo minimumPosition];)
    IGDStatement(CGPoint max = [touchInfo maximumPosition];)
    IGDFLog(IGDBG_DEBUG, SUBGESTURE, @"min=%f,%f max=%f,%f range=%f, time=%f", min.x, min.y, max.x, max.y, movementRange, timeDiff);
 ...

Conclusion

Feel free to use IGDebug.h as-is or however you wish in your projects. If you have improvements, I’d love to hear about them in the comments or on twitter.

I have been using a form of this in my projects since spring, and it is finally becoming a habit for me. Whatever tools you use, getting to the “I don’t have to think about this” level is important for your productivity, so choose a few and get in the habit of using them, whatever they are.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. I am writing this from the lobby during the pre-conference day of 360iDev in Austin, and I am really look forward to the conference.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

Adding subgestures to iOS gesture recognition

Filed in AppStoreOrBust, iDevBlogADay, iOS Development | Comments (2) |

I want users of my photo application to feel like they are physically manipulating their old stack of photos. To do that well, it needs the ability to respond to multiple simultaneous touches and movements in a consistent and coherent manner. UIGestureRecognizer provides an interpretive layer that I like, but it is designed around UIEvent and handles touches in sets.

UIGestureRecognizer’s multitouch recognition is elegant, but not exactly what I want. I hope to develop a set of classes for subgesture recognition that follows that style for individual touches, interpreting the user’s intent for each touch independent of other touches. For example, one touch may be interpreted as a pause or hold gesture, while simultaneously another touch is recognized as a single tap, and yet another as a swipe, all without regard to the UIEvent or when other touches began, moved or ended.

Multitouch Events and UIGestureRecognizer

In The Joy of Gesture Recognizers in iOS, I gave a quick overview of UIGestureRecognizer. It is an interpretive layer that takes the raw data of touches, applies some internal rules, and produces a higher level answer when it “recognizes” the user’s intent.

UIGestureRecognizer happens within the context of a single UIEvent. In all iOS touch handling, when the first touch is made, a UIEvent is created. As long as there is at least one touch still active, the UIEvent instance stays the same, and all touch events reference that same instance. Instances of UIGestureRecognizer use that behavior to decide between competing possible gestures. A single UIEvent instance may contain multiple touches but is usually interpreted as a single gesture. (The framework does support other options.)

The set of possible gestures is limitless, but only a subset are very useful. A simple programming exercise to explore multiple touch events can show some interesting possibilities. For instance, write a simple app that merely prints out individual touches and experiment with adding and removing touches within the same event. You will find that you can end up with five completely different touches than those you began with. Since this is all within the same UIEvent, they could all be used to create a very convoluted recognizer (not recommended.)

Generating Subgestures From Individual Touches

If you need to manage touches individually, you can ignore the UIEvent and track each touch yourself. But this means gesture recognition is all on you and the UIGestureRecognizer related classes will not help. The framework I am developing uses subgesture recognizers to interpret the timing and position of individual touches.

The core class is the custom gesture recognizer, IGIndividualSubgestureRecognizer. It’s primary responsibility is to track individual touches and delegate touch events to it’s list of subgesture recognizer (subclasses of IGSubgestureRecognizer) for subgesture recognition. Once an individual touch’s behavior has been recognized by one of the subgesture recognizers, all others will be cancelled. The current version is limited to recognition within a single UIEvent which means something like a single touch, double tap cannot yet be recognized. I want to add the ability to cross the UIEvent boundary in a future version.

IGIndividualSubgestureRecognizer maps each touch event to an instance of IGTouchInfo. These instances track the time and position of each touch event that subgesture recognizers can use to interpret the behavior. IGSubgestureRecognizer instances maintain the current state of each touch in relationship to itself. Once the touch reaches one of the final states for a particular subgesture recognizer, the controlling class IGIndividualSubgestureRecognizer will no longer pass on further events for that touch to that subgesture recognizer.

So if one IGSubgestureRecognizer instance recognized a subgesture for a given touch, then IGIndividualSubgestureRecognizer would set the state of that touch to cancelled for other IGSubgestureRecognizer instances. Once that happens, no instances would receive further events for that touch since one reached a successful final state, and the others reached a cancelled final state.

Subgesture recognizers inherit from IGSubgestureRecognizer. They only need to override the touch event methods and call the setState:forTouch: method when a gesture is recognized or not.

IGSubgestureRecognizer.h

@protocol IGSubgestureRecognizerDelegate<NSObject>
- (void) subgestureRecognizer:(IGSubgestureRecognizer *) subgestureRecognizer
                     forTouch:(IGTouchInfo *) touchInfo
                 changedState:(UIGestureRecognizerState) state;
@end

@interface IGSubgestureRecognizer :NSObject {
    NSMutableDictionary *touchInfoStateMap;
    IGIndependentGestureRecognizer *independentGestureRecognizer;
    id<IGSubgestureRecognizerDelegate> delegate;
}

- (id) initWithIndependentGestureRecognizer:(IGIndependentGestureRecognizer *) aIndependentGestureRecognizer delegate:(id<IGSubgestureRecognizerDelegate>) aDelegate;

- (UIGestureRecognizerState) stateForTouch:(IGTouchInfo *) touchInfo;
- (void) setState:(UIGestureRecognizerState) state forTouch:(IGTouchInfo *) touchInfo;
- (BOOL) isActive:(IGTouchInfo *) touchInfo;

- (void) reset;
- (void) touchBegan:(IGTouchInfo *) touchInfo;
- (void) touchMoved:(IGTouchInfo *) touchInfo;
- (void) touchEnded:(IGTouchInfo *) touchInfo;
- (void) touchCancelled:(IGTouchInfo *) touchInfo;

@end

IGSGRTap is an example of a simple single tap subgesture recognizer.

IGSGRTap.m

@implementation IGSGRTap

static NSTimeInterval maximumTimeDiff = 0.2;
static CGFloat maximumMovementRange = 5.0;

- (void)touchEnded:(IGTouchInfo *) touchInfo {
    CGFloat movementRange = [touchInfo movementRange];
    NSTimeInterval timeDiff = [touchInfo timeDifference];

    // a single tap is defined by the maximum time the touch was down,
    // and the maximum range it moved (allow a little shaking, but no real movement)
    if ((timeDiff < maximumTimeDiff) && (movementRange < maximumMovementRange)){
        [self setState:UIGestureRecognizerStateRecognized forTouch:touchInfo];
    } else {
        [self setState:UIGestureRecognizerStateFailed forTouch:touchInfo];
    }
}

- (void)touchCancelled:(IGTouchInfo *) touchInfo {
    [self setState:UIGestureRecognizerStateCancelled forTouch:touchInfo];
}

@end

IGSubgestures Project Will Be Released to GitHub at Some Point

I have the underlying subgesture recognition working, and will be adding recognizers to match these recognizers available in the UIGestureRecognizer family:

  • Single Tap Gestures
  • Swipe Gestures
  • Pan Gestures
  • Long Press Gestures

Once those are working, I want to add things like flick gestures and single touch spin gestures.

I will be posting the code to github at some point, no promises on exactly when, but I do hope to have a version uploaded before November is over. I will write up a new blog post when I publish the code, so if you are interested, either follow me on twitter, or subscribe to my RSS feed. The license will be something very simple so that you will be able to use it in your own code with no worries.

Please let me know what you think on twitter or in the comments below.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

Advice for Indie developers with young families

Filed in iDevBlogADay, Miscellaneous | Comments (3) |

Take advantage of those serendipitous moments

Twelve years ago, I went independent full time with kids aged 11, 10, 8, and 6 (the youngest just stared college this fall.)

One of the great parts was my ability to alter the day’s schedule on very short notice. There are so many cool things you can do that cost very little but help create memories for a lifetime, especially with younger kids. I am very grateful that I was able to take advantage of my independence in many big and small ways.

Sometimes, the best things come together quickly, and as an indie, you are in a position to take advantage IF you are watching for them. A beautiful early spring day becomes an afternoon bike ride with work pushed to later in the evening. A rainy summer afternoon turns into a mudsliding event for you and the kids. When you get stuck on something, sometimes the best antidote is throwing a frisbee around or playing whiffle ball in the back yard. And the sledding hill is great fun on those snow days!

Include family events in your plans and schedule

Trips to special places can be much less crowded during the week, often cheaper as well. Museums on a weekday are wonderful, camping in the middle of the week instead of crowded weekends gives a much more relaxed time.

With a flexible schedule, you may be able to participate in more of your children’s activities. Coaching youth sports becomes easier to schedule, watching ballet practice or attending concerts, especially when you have multiple kids, can be much less stressful. Taking your kids and their friends to a matinee of the latest Pixar event can be a lot of fun (and very noisy!)

Invest time in building relationships with your kids when they are young

The single, best piece of advice I can give you to prepare yourself for adolescence is to develop a solid relationship with each of your children before they reach that stage.

Infants and very young children quickly develop a complete trust in you as parents that will last for their first few years. A key task for you between those early years and adolescence is to take that trust that is given without reservation, and develop it into a trust based on love, knowledge, and real events. Through the elementary years, work towards giving your children reasons to hold onto and build on that trust. You want them to know that even when they don’t agree with you, you always have their best interest at heart.

As they get older, they may not acknowledge that they can trust you, and may even deny it outright, but it will be an undercurrent to their thoughts, and it will certainly be an influence in their life.

Seize the day

Enjoy these days. They can be stressful, tiring, and tons of work, but enjoy the bright spots.

Remember, the best family memories are built through the drip drip drip of many simple events that occur regularly over the years.

I know it’s almost a cliche, but this time will pass incredibly fast. So, seize the day.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

The Joy of Gesture Recognizers in iOS

Filed in AppStoreOrBust, iDevBlogADay | Comments (3) |

Choosing Gestures for an App

Gestures play a role in an iOS app similar to that of game mechanics — they are the primary contact your user has with your app, and it is important to get them right. Choose something cutting edge, and your users may just not get it. Choose to use just the old, basic ones, and your app will probably not be taking full advantage of the iOS environment. Take a standard gesture and give it a different meaning than most apps, and you will most definitely confuse the user.

Your gestures should:

  • Feel natural to your user in the context of your app’s primary purpose (it does have a single, overriding purpose, does it not?)
  • Not violate standard and expected usage if it is a gesture commonly used across apps
  • Be consistent with other gestures used within your app
  • Be as simple as possible and still accomplish their intended goal

I am implementing a simple, continuous photo stream and wanted a set of gestures to easily manage the flow. I needed gestures to manipulate the stream by:

  • Starting it moving,
  • Speeding it up,
  • Slowing it down,
  • Reversing its direction,
  • Temporarily pausing it,
  • Manually moving the stream back and forth while paused.

I decided to use standard swiping gestures to control the direction and speed of the photo stream, and a custom continuous gesture recognizer to implement the pause and manual movements.

The Joy of Gesture Recognizers

Gesture recognizers were introduced in iOS 3.2 for use with the iPad, and later in iOS 4.0 for the iPhone and iPod Touch. If all you need are the built-in gestures (there are six), then you may not have to deal with touch events directly at all.

I am using two instances of UISwipeGestureRecognizer to handle the swipe left and swipe right gestures to control the main flow of the photo stream, but none of the other standard recognizers worked for my pause and move gesture. UIPanGestureRecognizer only takes effect once movement is detected, and I need the pause to be effective on first touch. UILongPressGestureRecognizer handles the pause correctly but fails once movement is detected. The gesture processing allows me to customize how recognizers interact with each other, but not in a way I needed. Fortunately, it is pretty straightforward to add a custom recognizer, so I wrote PauseAndMoveGestureRecognizer.

Multiple Gesture Recognizers

My custom recognizer is a continuous recognizer. That means my app receives events when recognition begins, for each movement, and when the gesture ends. I pause the photo stream when recognition begins (upon first touch), and manually move the stream back and forth depending on the movement events generated while the touch is still active. Upon receiving the gesture end event, I allow the photo stream to continue moving as before.

The swipe gesture recognizers are used to change the speed and direction of the photo stream. For instance, by repeatedly swiping left, you can speed the stream up in that direction. Swiping right would then slow the stream down, and so on.

Conflicts Between Gesture Recognizers

An important issue to consider is what behavior you want when multiple gestures are possible at the same moment. When my photo stream is moving across the screen and I touch the stream, it could either be the beginning of UISwipeGestureRecognizer or PauseAndMoveGestureRecognizer. I initially tried to use a single touch for both types of gestures, but could not find a reliable method to do so because of the interaction between my custom recognizer and the other gestures.

By default, gesture processing will generate multiple gesture events for the same set of touches (assuming they fit the pattern of each.) The simplest example is including both a single tap gesture and a double tap gesture: in order to have a double tap, by definition you will first have a single tap. The default behavior is to send both events so that your app will first receive the single tap event, then the double tap event.

I used a timer ([NSTimer scheduledTimerWithTimeInterval:...]) to set a threshold for the pause, and it worked fine when it was the only recognizer involved, but it did not trigger the “Began” event when the swipe gesture recognizers were also included. I assume I was violating some assumption or restriction of the gesture processing by using my own timer event inside the recognizer. (I ended up doing something slightly different which I like better anyway.)

My next attempt was to call the ‘requireGestureRecognizerToFail’ method on my pauseAndMoveGestureRecognizer instance for each of the swipe gestures. By doing this, when either of the swipe gestures is recognized, the gesture processing will cancel my pauseAndMoveGestureRecognizer. If the gesture processing determines that neither swipe gesture is possible, then processing of my custom recognizer continues.

Unfortunately, even though my processing continued, the timing of the events was not what I wanted.

My Custom Gesture Recognizer: PauseAndMoveGestureRecognizer

What ended up working the best was making the swipe gestures require two touches, and the pause and move gesture a single touch. I think this will be clearer to users and also removes any delays, however slight, in pausing the stream.

As you can see from the code below, there is not too much to creating a custom recognizer. Right now, I can’t envision gestures I would want that would not be possible using the UIGestureRecognizer classes.

PauseAndMoveGestureRecognizer.h

//
//  PauseAndMoveGestureRecognizer.h
//
//  Created by Douglas Sjoquist on 10/17/10.
//  Copyright 2010 Sunetos, Inc. All rights reserved.
//

#import <UIKit/UIGestureRecognizerSubclass.h>

@interface PauseAndMoveGestureRecognizer : UIGestureRecognizer {
    BOOL pauseStarted;
    NSUInteger numberOfTouchesRequired;
}

@property(nonatomic) NSUInteger numberOfTouchesRequired; // default is 1.

- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end

PauseAndMoveGestureRecognizer.m

//
//  PauseAndMoveGestureRecognizer.m
//  BrowsePhotos5
//
//  Created by Douglas Sjoquist on 10/17/10.
//  Copyright 2010 Sunetos, Inc. All rights reserved.
//

#import "PauseAndMoveGestureRecognizer.h"

@implementation PauseAndMoveGestureRecognizer

@synthesize numberOfTouchesRequired;

- (id) initWithTarget:(id)target action:(SEL)action {
    if (self = [super initWithTarget:target action:action]) {
        self.numberOfTouchesRequired = 1;
    }
    return self;
}

- (void)reset {
    [super reset];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];

    if ([touches count] == self.numberOfTouchesRequired) {
        self.state = UIGestureRecognizerStateBegan;
    } else {
        self.state = UIGestureRecognizerStateFailed;
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];

    self.state = UIGestureRecognizerStateChanged;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];

    self.state = UIGestureRecognizerStateEnded;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];

    self.state = UIGestureRecognizerStateCancelled;
}

@end

Update

Gesture recognizers are only doing a few simple things with touch events on your behalf so your view does not need to handle them directly.

When multiple recognizers are in play, the combination can be a little confusing, but the advantage of the recognizers is that each of them is looking for a single pattern of touch events. So although the interaction between recognizers may be complex, the internal behavior of a single recognizer remains relatively simple. As long as the set of touches does not violate what the recognizer expects as part of a gesture, it will remain “Possible”. At some point the recognizer will decide to accept or “Recognize” the gesture, or forget about it and “Fail” (for discrete gestures).

Recognizers still need to decide how to handle complex situations, just like you do with traditional touch event handling. Putting one finger down then another after a slight delay is an example of that–the recognizer will receive multiple ‘touchesBegan’ events with different sets of touches and must decide what to do about it. Well written recognizers will handle it smartly and consistently.

The benefit of using standard recognizers is that it simplifies your code, removing details from the main body of your work so you no longer have to worry about them. Also, by using them, you are simply following the standards for simple gestures that Apple is promoting, so your app will behave more like other apps on the device.

For custom recognizers, there are two benefits. One is that your recognizer only needs to be looking for a single pattern of events, keeping the code tighter and cleaner. Another is that once a recognizer fails or is cancelled, the gesture processing acts as a filter so that no further touch events with that particular set of touches will be sent to your recognizer.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

Good News and Bad News

Filed in AppStoreOrBust, iDevBlogADay, iOS Development | Comments Off |

Good news — Finding my iOS development rhythm

I have finally managed to get into a good iOS development rhythm over the last several weeks, focusing on my personal iOS projects most of Friday and Saturday, and one or two other evenings during the week. Finding my stride has helped make me much more comfortable in Xcode and the iOS frameworks, and it only takes me a few minutes at the beginning of a session to get back into the flow of iOS.

Bad news — Distractions

Unfortunately, I allowed myself to get distracted from my primary goal for more than a week of that productive time.

Reading a blog post one weekend gave me an app idea I found hard to resist. At first, I was smart. I recorded the idea and some thoughts in my development wiki, and convinced myself to leave it alone. That resolve lasted about three days before I gave in. I deluded myself into thinking I could take the “new shiny” from it’s box and only play with the idea for one evening, but one evening turned into several sessions in a row before I managed to put it back into its box.

I still think the idea has merit, but the allure has worn off enough that it won’t distract me for a bit. (Of course, there is this other idea I just had that will take the app store by storm!)

Current development challenges

My primary goal is developing my photo browser app, and I have prototyped several variations on some ideas I want to incorporate.

I developed a simple wrapper for loading groups and photos using the asset library framework that should be easily extended so I can handle multiple photo sources. I have resisted the urge to build involved hierarchies and large frameworks, and constrained myself to developing some fairly simple protocols. The very basics work now, there are only one or two more features I want to add to the base functionality that my core app needs.

I am currently experimenting with various photo browsing techniques using core animation, and so far it seems promising. This is my first serious use of core animation, so I still have a lot to learn, but @neror’s CA360 project on github has been very useful, as well as Bill Dudney’s Core Animation book published by the Prags.

In typical development fashion, each answered question generates several new questions and problems. I have enough experience to know that most of my problems are the result of limited understanding, misusing a framework somehow, or otherwise doing something stupid.

Some of my current open issues are:

Unexpected pauses in CAKeyframeAnimation

In one of my prototypes I built a single CAKeyframeAnimation animation to move an image across the screen using multiple curve path segments. It pauses slightly at the transition between segments, acting like it takes a small but noticeable amount of time to compute the next segment. I am not comfortable enough with core animation to judge whether I am misusing the framework somehow, or just doing something wrong. Hopefully I will find out this week.

EXC_BAD_ACCESS errors

This evening I encountered EXC_BAD_ACCESS errors in another prototype. I have a very simple framework to handle multi-step animations using blocks which works as expected (except for the EXC_BAD_ACCESS). The EXC_BAD_ACCESS errors occur when accessing values outside the block. I am fairly certain I am creating the blocks correctly, and using them like I have in several other prototypes. But I obviously still have an error, so decided the wisest course was to step away from the code for now and come back to it later this week.

Deciding on best method for photo streams

Several of my experiments have been to help me decide whether core animation is the correct approach for my photo streams. I’d love to let it handle that portion of my app, but I have not gotten far enough to know whether I will be able to use it the way I envision.

What’s next

I am thinking about whether it would be useful to setup a landing page to gauge interest, and if so, how far along I should be in prototyping, experimenting, and customer discovery before I do so. This is all very new to me, so I have continued reading and skimming a lot on the subject. I still need to figure out a way to connect with potential users, but for the moment that is still on the back burner to development experiments.

I am encouraged that as I work on this app, my interest and expectations for it grow. Hopefully I will be able to stay in the flow over the coming weeks and make good progress before 360iDev in Austin. I really want to have a solid core of my app working by then because I know I can get some great feedback from my fellow developers there.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

Today, I choose to be thankful

Filed in iDevBlogADay, iOS Development | Comments (5) |

Frustration

I felt frustrated this week: with my consulting work, with my iOS projects, with my schedule — and it showed.

Sometimes when I feel that way, I focus on the frustrations. But, “that way madness lies, let me shun that”.

Thankfulness

Today I choose to focus on what I have, on what I *can* do, on what is possible.

Today, I choose to be thankful.

Amazing tools

I am thankful that I live in a time where there is so much creative potential sitting here on my desk. It amazes me to think that I have access to literally (really!) everything I need to more than provide for my family’s needs, to pursue a career that invigorates me, to make the bold attempt to follow my dreams.

I have more information in the electronic books, documentation, and other notes sitting on my laptop right now than was available anywhere when I first started programming.

Through a chunk of electronics and plastic smaller than my thumb, I have wireless access to more useful information than I could digest in a dozen lifetimes.

Sitting on my hard drive are interpreters, editors, and compilers that would be the envy of the world during the first three decades of computing history.

And on some days, I am so nonchalant about it all that I am like a spoiled prince who views the entire kingdom as his playground and birthright.

But, today, I choose to be thankful for my tools.

Incredible community

I am thankful that I am surrounded by thousands of creative individuals who are willing to freely share what they have learned through months and years of painstaking work. Somewhere out there right now, someone is working on a tool, an article, or an application that in the coming weeks will be made public and ease my workload by an order of magnitude. And they will ask nothing in return.

This year thousands of talented individuals will share vital technical information with their competitors through books, blogs, and conferences without any direct economic return.

And on some days, I take this community of friends, peers, and experts for granted.

But, today, I choose to be thankful for the community of developers who freely share with me.

Supportive family

I am thankful for a wife who supports me even though she doesn’t grok what I do at all. When I sit and think for hours, or bury myself into my work late into the night — she understands. When I get stuck or worried, she helps me work through my frustrations. When I am just plain weird, she still loves me.

I am thankful for four grown children who accept the geekiness of their dad, who show interest in those arcane details I sometimes bring to the dinner table, and who bring me more joy than they know.

And on some days, I assume that they will always be there for me.

But, today, I choose to be thankful for my family.

Loving God

I am thankful for a God who loves me unconditionally, and has created this wonderful world to explore.

It is a privilege to dive into the myriad details of this world and realize that every question that gets answered opens up dozens more. The depth and intricacy of life, the universe, and everything reminds me of how great He is, and how much I still have to learn.

And on some days, I selfishly acknowledge no one outside my own mind.

But, today, I choose to be thankful for my creator.

Think on these things

When you get frustrated by thorny technical problems, by difficult coworkers, or even personal struggles, I encourage you to make your own list of good things, and to think on those things.

You might be surprised how much good it will do you.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

iOS Asset Library photo browsing experiments

Filed in AppStoreOrBust, iDevBlogADay, iOS Development | Comments (1) |

My photo browsing work has gone in fits and starts over the last two weeks, but I have made some progress through experimentation. Since upgrading to an iPhone 4, and the subsequent announced availability of iOS 4.2 on the iPad, I can now use the Asset Library framework in my prototypes. I want to use other photo sources eventually, but my first version will use the photo albums available on the device.

Experiments with Asset Library lead to experimenting with blocks and Grand Central Dispatch

One of features I want in my app is a photo stream that moves automatically across the device in some fashion, but still allows the user to control the pace. The first step was to build a simple prototype that browsed through the photo albums currently synced to the device.

The Asset Library framework is fairly small and handles all access to on device photos, videos, and the associated albums. Each photo or video is an “asset” in the library. The entry point is through the enumerateGroupsWithTypes:usingBlock:failureBlock: method in the ALAssetLibrary class. As you can tell by the method name, this method makes use of blocks to accomplish its work.

Objective-C blocks are very clean and crisp, taking care of otherwise messy implementation details such as automatically retaining and releasing objects referenced by the block. The syntax for the simplest executable block is:

^{}

which obviously doesn’t do very much, but clearly is not encumbered by extra baggage. A block is a closure that captures the state of any references external to the block and maintains them during the life of the block. Many languages and environments offer closures, and if you come from the Java world like I do, they are a welcome relief from the not-quite-good-enough nature of anonymous inner classes. It is very nice to be able to work with them in iOS.

Another feature of the latest versions of iOS that comes in handy with browsing the photo albums is Grand Central Dispatch (GCD). GCD was introduced to OS X in Snow Leopard, and to iOS in version 4.0. Many of the tasks that used to require creating separate threads can now be handled much easier and cleaner with GCD and blocks.

Here is one method from a very simple example that loads all the asset references on my phone into a mutable array ‘assets’ in the background while updating a simple status label on the main thread with the current asset count:

- (void) updateCount {
    self.statusLabel.text = [NSString stringWithFormat:@&quot;Count: %u&quot;, [assets count]];;
}

- (void) loadLibrary {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(queue, ^{
        void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
            if(asset != NULL) {
                [assets addObject:asset];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self updateCount];
                });
            }
        };

        void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) =  ^(ALAssetsGroup *group, BOOL *stop) {
            if(group != nil) {
                dispatch_async(queue, ^{
                    [group enumerateAssetsUsingBlock:assetEnumerator];
                });
            }
        };

        [library enumerateGroupsWithTypes:ALAssetsGroupAll
                               usingBlock:assetGroupEnumerator
                             failureBlock: ^(NSError *error) {
                                 NSLog(@&quot;failure&quot;);
                             }];
    });
}

I do not completely understand all the interactions between GCD queue, the main thread, and the asset library enumeration. There is not a lot of information in Apple’s documentation about exactly what is going on, but it appears that each enumeration happens on the main thread, even if the caller is run from an asynchronous queue which is *not* on the main thread.

To ensure the loading does not tie up the main thread, and thus prevent GUI updates, I enclosed the call to “group enumerateAssetsUsingBlock…” in a block (lines 20-22) and put that block on the default queue to be run in the background as well. This particular pattern will load each asset in the background, but update the status label in the main thread properly.

Lines 12-14 illustrate the GCD method of running code on the main thread. It looks cleaner to me than calling performSelectorOnMainThread, and is certainly more flexible since it can include any code you wish.

Feedback from non-techies

In addition to experimenting with several different ideas and prototypes based on the Asset Library, I also was able to show a simple photo stream demo to an avid iPad user (my daughter!) while we were visiting my grandson last week. I think I conveyed my ideas fairly well to her, and although she doesn’t yet have an iPad (but wants one), nor does she yet have multiple thousands of photos, she is quickly heading that way. She is also the one who did much of the scanning and sorting a few years ago, so she has an idea of the pain point I am trying to address. She thought it a reasonable approach and as I turn my simplistic prototypes into a more complete app, I hope to get more detailed feedback from her and others.

360iDev Austin, November 7-10th

I finally sorted through my schedule for the fall and registered for 360iDev in Austin this November. If you are like me, and receive most of your iOS encouragement and growth virtually through the internet, you need to attend. I am as much a lone wolf as any developer out there, but the motivation and encouragement I receive from the iOS community through 360iDev keeps me coming back.

I am really looking forward to visiting with old friends and fellow iOS developers, to participate in the game jam, to learning more about iOS development and techniques for building an indie software business, and to being encouraged and motivated in my iOS development. You should register too!


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

Useful podcasts for Indie iOS Developers

Filed in iDevBlogADay, iOS Development | Comments (3) |

Since it is time consuming to sort through all the resources on the internet and find useful stuff, I decided to share which podcasts I find useful as an indie for today’s iDevBlogADay post. (I have made progress on my iPad photo app, and hope to report on it next week.)

I do not have a fixed podcast listening schedule, but I eventually listen to almost every episode of the first five on my list. I only listen to selected episodes of the last three, partly because there are so many episodes. I usually listen to podcasts while working around the house or running errands since I prefer silence or music to help me focus while I work.  When I listen, these are my current selections and priorities:

  1. MDN Show
  2. Startups For the Rest of Us
  3. Dim Sum Thinking
  4. Core Intuition
  5. IRQ Conflict
  6. The Startup Success Podcast
  7. Small Business Marketing Blog from Duct Tape Marketing
  8. Mixergy

#1 MDN Show

At the top of my list is the Mac Developer Network show. It is hosted by Scotty (Steve Scott), @macdevnet and John Fox, @djembe.  The MDN show comes out roughly twice a month and each show is around 90 minutes long. It is a magazine format with a mix of regular segments, discussion of events in the Mac or iOS world, and developer interviews.

I enjoy the variety of segments and the community that Scotty has developed around MDN. The show is currently on summer break, but should be returning shortly — I look forward to the next episode.

From the MDN web site:

The Mac Developer Network Show (The MDN Show) is a one stop show for Mac, iPhone and iPad Software Developers. Enfolding, embracing and including some classic Mac developer podcasts such as Late Night Cocoa, The Mac Developer Roundtable, The Mac Software Business Podcast, Developer Lives and CocoaFusion as well as adding features such as news, views, reviews and the now infamous World According Gemmell in an easy to listen to magazine style format.

#2 Startups For the Rest of Us

This has become one of my favorite podcasts for advice and tips on indie based business. It is hosted by Mike Taber, @singlefounder, and Rob Walling, @robwalling, both of whom have solid backgrounds in micro-ISV businesses.

The focus is not platform specific, but each show has clear advice that you can easily adapt to your iOS based business. I do not keep most podcasts I listen to, but I have kept a number of their shows, including:

  • Episode 4, 8 Things We Wish We Knew When We Started Out
  • Episode 6, How to Get Traffic to Your Site
  • Episode 9, Our Biggest Startup Mistakes
  • Episode 11, The Five Biggest Hurdles to Getting Started

If you find any of the shows worthwhile, I would suggest start back with episode 1, and follow through to the present.

From Startups for the Rest of Us web site:

Welcome to Startups for the Rest of Us, the podcast that helps developers be awesome at launching software products. Whether you’ve built your first product or are just thinking about it. We are Mike Taber and Rob Walling. Combined we have over 20 years of experience as software entrepreneurs and we’re here to share those experiences to help you avoid the mistakes we’ve made.

#3 Dim Sum Thinking

This is a new podcast by Daniel Steinberg, @dimsumthinking. Each weekly show is relatively short and focused on a single topic related to professional and personal development told in a unique way.

I have really enjoyed Daniel’s story telling approach, and I look forward to new episodes.

From Daniel’s About page:

Apple gives third party developers the same advice. So many iPhone developers want to open up the development tools and start writing code. Apple’s advice is that you stop and identify carefully who your audience is and what problem they will be able to solve or task they will be able to accomplish with your app. Spend time prototyping your app on paper and really working on the human interaction before you write a line of code. Identify the audience and the story and story board your app just as someone might sketch out scenes in an animated feature.

#4 Core Intuition

Core Intuition is primarily a discussion between the hosts about a wide range of topics pertinent to developing for the Mac. It ranges from technical discussions of new Apple frameworks to conferences to handling user support to marketing your software. It is hosted by Daniel Jalkut, @danielpunkass, and Manton Reece, @manton.

I like the variety of the discussions, and even though not every show has something directly applicable to my day to day work, it helps give me a broader perspective on developing a software based business.

From Core Intuition’s web site:

Core Intuition is a podcast about the process and life of Mac development.

#5 IRQ Conflict

IRQ Conflict is a short podcast which began earlier this year and comes out roughly twice a month. The format is similar to the old “Siskel and Ebert” movie reviews where the two hosts, one a Microsoft developer, and the other a Mac developer, react to a series of tech items in the news. It is hosted by Justin Williams, @justin, and Mikel Berger, @mikelberger.

Living in an iOS world (and in my case an iOS and Java world), I can easily lose touch with the perspective outside those worlds. This short podcast is entertaining, and occasionally provides a perspective I might not have considered.

From IRQ Conflict’s web site:

Apple Developer. Microsoft Developer. FIGHT!

Debates about the 5 top tech stories from the past few weeks. All in about 10 minutes.

#6 The Startup Success Podcast

The Startup Success Podcast interviews someone different each week ranging from consumer startups using technology to enhance their core business to technical startups that sell software or services. It is hosted by Bob Walsh, @bobwalsh, and Patrick Foley, @patrickfoley.

I have been listening to the Startup Success Podcast longer than any other business oriented podcast, and even though I don’t listen to every show, I listen to most and usually benefit from the interviews.

From the Startup Podcast web site:

The mission of The Startup Success Podcast is simple: make microISVs, startups, Mac indies and everyone pursuing the dream, challenge and reality of starting their own software company more successful. Each week, we hope to bring you about 20 minutes of valuable information on the business, technical and social developments, tools and trends that will give you an assist in your startup.

#7 Small Business Marketing Blog from Duct Tape Marketing

Duct Tape Markerting is not a tech focused podcast by any means, but there is enough variety that you will find useful information here. It is hosted by John Jantsch, @ducttape.

I do not listen to every show but the content and interviewees in this bi-weekly podcast are diverse enough that I usually listen in full to an episode every month or so.

From the Duct Tape Marketing web site:

His blog was chosen as a Forbes favorite for marketing and small business and his podcast, a top ten marketing show on iTunes, was called a “must listen” by Fast Company magazine…His practical take on small business is often cited as a resource in publications such as the Wall St. Journal, New York Times, and CNNMoney.
“John Jantsch is the Peter Drucker of small business marketing tactics.” — Seth Godin, author of Linchpin
“Business blogger John Jantsch, a Kansas City marketing consultant, has built quite a following with his Duct Tape Marketing site. The blog provides small-business readers with successful marketing techniques that don’t require a large budget to execute.” — Harvard Business School

#8 Mixergy

Mixergy is really a video interview show, but I subscribe to the audio podcasts. There are far more shows than I could watch or listen to, even if they applied (multiple hour long shows per week), but I do subscribe to the feed to keep an eye out for interesting interviews. It is hosted by Andrew Warner, @AndrewWarner.

Many of the interviews do not appeal to me, but there is usually one or two a month that I really find useful or captivating. I have kept a couple of Mixergy interviews, including:

  • How Shopify Became Profitable By Helping Anyone Open An Online Boutique with Tobias Lütke
  • DODOcase: How An iPad Case Generated Almost $1 Mil In Revenue Within 3 Months with Patrick Buckley

From Mixergy’s web site:

The Mixergy Mission

The Mixergy Mission is to introduce you to doers and thinkers whose ideas and stories are so powerful that just hearing them will change you.

The Mixergy Mission is to give you an alternative to the “know-it-all, professional gurus.” I want to convince you that no single person knows it all. I want to show you that the best way to grow is to learn from a mix of smart people who are willing to share their expertise and experiences.

The Mixergy Mission is to infect you with a passion for business and then help you build your business.

The Mixergy Mission is to encourage YOU to have a mission, not just a startup, not just a company, but a calling.

The Mixergy Mission is to act as a counter-weight to all the venture capitalists who’ll try to convince you that the only reason to build a business today is so you can flip it tomorrow. The world isn’t changed by people who have an eye on the exit.

The Mixergy Mission is to convince you to follow a vision so big and important that you can’t do it alone. Then I want to give you a mix of wicked-smart people who will help you achieve it.

The Mixergy Mission is too big for me to achieve alone. If what I’m describing here calls to you, jump in and join me.


As an indie developer, one of the best things you can do is to find like-minded developers that will provide encouragement and motivation while pursuing a commitment. A great collection of indie iOS developers have helped me stay on track, most of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. If you can make it to Austin in November, I highly recommend it for its content, the friendships you’ll develop, and the passion it will bring to your iOS development.

Also, here is a little more information about me, Doug Sjoquist, and how I came to my current place in life. You should follow me on twitter and subscribe to my blog. Have a great day!

A problem to solve

Filed in AppStoreOrBust, iOS Development | Comments (8) |

Finding the pain

Old Slides and PhotosI have a confession to make. I take a ton of photos.

From 1982 when I got married until about 1999 I took thousands of slides and prints (I have four children and dozens of extended family members.) Since 1999 I have been completely digital and taken thousands more. Most of our slides and prints are now scanned and I have over 15,000 digital photos — all synced to my iPad which has become a very fun family photo album.

In the last five years I have built a dozen slideshows for open houses, graduations, weddings, and anniversaries. Each of those slideshows turned out well, but required many hours of work. Scanning physical photos is a very labor intensive task, but fortunately I am close to 90% complete in that task.

I have tried many different photo organization methods over the years, but currently have a very simple method: I keep a separate folder for every slide tray, every print album, and every month of digital photos.

But, something that still takes much more time than I would like is finding the photos I want to include in a given slideshow.

I plan to build something to ease that pain point.

Past attempts to ease the pain

My first “major” slideshow was for my oldest daughter’s high school graduation and open house. We homeschooled our children, so this was a very personal and exciting time for us, and I wanted it to be special.

During that year I purchased a slide scanner, and she scanned in all our slides (from her birth in 1987 until my Pentax SuperME died in 1997), and select photos from the albums between my slides and digital camera era. By the time she was finished, we had over 10,000 photos to search through to produce the slideshow — a bit overwhelming.

I don’t remember exactly what software I tried during that time, but I know I looked at dozens and tried most of them at least a little. I do know that I could not find anything very useful for selecting the photos I wanted — so I did what any good hacker does, I rolled my own.

Through several iterations, I ended up with a simple Delphi application (once my favorite development environment!) that would allow her to quickly browse all those photos and identify all the ones where she appeared. It worked pretty well given it’s limitations, but by judicious use of workarounds and copying of directories, it helped us narrow the 10,000+ photos to around 3,000 that had her in them. We then used the same application to select out a subset of those 3,000 to produce a set of photos we wanted to use in the slideshow. I used slightly enhanced versions of that application and other simple methods for my oldest son’s graduation in 2007, second son in 2008, and youngest daughter in 2010.

For other slideshows I have used simple methods such as general file browsing using my MBP and copying the photos I wanted to a new directory. Not terribly difficult, but pretty time consuming.

What I really want

Until Google or someone develops image searching as good as the text web crawling available today, I do not think any completely automated method of finding photos will ever satisfy me. I would love to tag all my photos with names, events, places, etc., but even if facial recognition improves a great deal, doing so will remain an intensively manual process.

Now that I have an iPad with a copy of all my photos, it is amazing how quickly I can flow through photos and find individual photos I had forgotten about. I want to take that ease of browsing on my iPad and apply it to quickly select a set of photos that can then be turned into a slideshow.

My App idea

My target customer is someone who has thousands of digital photos, probably only loosely organized, and wants to select a subset of those photos for a slideshow or other display.

The initial requirements for my iPad app are:

  • create a project that will hold the state and can be edited later,
  • select photos from iPad albums,
  • attach a playlist,
  • play slideshow on iPad or through video out.

Current status

Initial MockupI first started mocking up something like this at the iPadDevCamp in San Jose last April. The purpose of iPadDevCamp was to show what could be done within the constraints of the existing platform, but since iOS 3.x does not allow access to to photo albums on the device, I shelved the idea. It has now been announced that iOS 4.2 will be available on the iPad, so my idea is viable again.

During iPadDevCamp, I came up with some screen ideas using iMockups that are my starting point this week. I shared those ideas with other developers there and received useful advice, and will take that into consideration as I develop some prototypes. I have talked with some local iPhone users about my idea, but not in detail, and none of them are iPad owners.

This week I began exploring the AssetsLibrary framework in the iPhone simulator, but will have to wait for a 4.2 beta SDK before I can play with the iPad simulator or device. Since I will need some photo sources in the meantime, I spent some time experimenting with other options, and decided to start with a simple ftp based photo loader for now.

What’s next

It is vital to find potential customers early so I can validate my ideas, but that will definitely be a challenge for me. I am reading through Steve Blank‘s book “The Four Steps to the Epiphany”, about his customer development process and even though it is probably geared towards multiple developer startups, it has given me some insight into how to begin.

Once I have a simple photo loader to simulate photo album access, I will begin prototyping various ideas. I have learned to treat my prototypes as disposable code so I can move quickly, hopefully I will stick to that.

My task list for this next week:

  • Prototype methods for quickly browsing a set of photos,
  • Begin building a customer development plan,
  • Find at least one local iPad user with a decent collection of photos.