October 2010

Adding subgestures to iOS gesture recognition

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

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 Off on Advice for Indie developers with young families |

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 iDevBlogADay | Comments Off on The Joy of Gesture Recognizers in iOS |

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 iDevBlogADay, iOS Development | Comments Off on Good News and Bad News |

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 (0) |

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!