iOS Development

Creating an Xcode project template with GHUnit and OCMock

Filed in iOS Development | Comments (2) |

I use GHUnit and OCMock in my app development, but each time I set up a new project in the past, it felt klunky and error prone. I either copied an old one to start and renamed and deleted things, or I created a new one and dragged chunks from old projects into it. I grew weary enough of this process that I decided it was time to create an Xcode project template with my typical setup.

I recently created an Xcode project template to do all this, and I decided to write a step-by-step description to help others do something similar. It is a simpler project than my template, but covers all the required steps. It might be useful to you as-is, or perhaps it just gives you the one missing piece in your battles with GHUnit, OCMock, or project templates.

These instructions are based on:

and will cover these steps:

  1. Create a base application project
  2. Add a GHUnit based application test target
  3. Add OCMock to the application test target
  4. Create an Xcode project template from the project

General comments

I highly recommend creating a local source control project to save your work as you progress. Commit your changes often enough to make things easier on yourself. My practice is to do one thing at a time, get it working, and commit to my local .git repository. Every so often, usually after a major subtask is complete, I will also push my changes to a remote git repository.

These instructions will create a project structure with all files stored in the actual project directory, including the GHUnit and OCMock frameworks. It is better for your template to embed its dependencies rather than depend on external references.

These instructions assume everything we create or download will be in the directory ~/xcpt, but feel free to put them wherever you like.

After each step in the process, you should do a clean, build, and run for each target to validate the configuration and dependencies, and make sure your VCS includes all files and you have committed your changes.

I create projects and templates with more structure and configuration options than we will cover here. In order to focus on the core issues, I will be creating a simpler project structure than I normally use. I would suggest you create the simple project and template here first to ensure the steps work for you. Then create a customized version that matches how you normally set up your projects.

We will use the name TemplateBase for our project and derive several targets and file names from it. You can choose whatever name you wish, but for ease of editing the final project and turning it into a template, be consistent in your naming.

There are many more options for GHUnit, OCMock, and project templates, but they are outside the scope of these instructions. For more information, see the Other Links at the end of this post.

1. Create a base application project


xcptStep1a.pngThese instructions start with the Tab Bar Application template, but you should be able to build your template based on any of the standard application templates.

This step is straightforward but provides a baseline on which we can build our project.

  • Create a new subdirectory xcpt in your home directory
  • Open up Xcode, and create a new project based on the Tab Bar Application template
  • Save the project as TemplateBase in ~/xcpt
  • Make sure the project builds and runs in the simulator without error

If you like positive reinforcement, congratulations, step 1 is complete! If not, let’s move on anyway.

2. Add a GHUnit based application test target


xcptStep2a.pngFirst, we need to add a test target to our project. GHUnit runs as as a standard application target, so create a new application target named TemplateBaseTests.


xcptStep2b.pngAdd the existing frameworks in our project to this target by selecting them as a group, right-clicking them, and checking TemplateBaseTests in the Target Memberships list.

Next, we need a copy of GHUnit. Download the latest version, 0.4.27, from github, and unzip it into ~/xcpt.


xcptStep2c.pngOpen the ~/xcpt folder in Finder and drag the GHUnit.framework directory to the Frameworks group in your project. Make sure you:

  • Check “Copy items into destination group’s folder (if needed)”
  • Uncheck TemplateBase in the Add to Targets window,
  • Check TemplateBaseTests in the Add to Targets window


xcptStep2d.pngNow create a new group called “Test Classes”. Edit the info for the group, and under the Target tab, assign this group to TemplateBaseTests.


xcptStep2e.pngCreate a new class named SampleTestCase in the Test Classes group. We do not need a header file for our unit test classes, so uncheck “Also create SampleTestCase.h”.


Replace the entire contents of the file with the following code:

#import <GHUnit/GHUnit.h>

@interface SampleLibTest : GHTestCase { }
@end

@implementation SampleLibTest

- (void)testSimplePass {
	// Another test
}

- (void)testSimpleFail {
	GHAssertTrue(NO, nil);
}

@end


xcptStep2f.pngOpen up the info dialog for the TemplateBaseTests target, and select the Build tab. Select “All configurations”, then find the “Other Linker Flags” setting and add “-all_load” and “-ObjC”.

Now select TemplateBaseTests-Info.plist and clear the value for the “Main nib file base name” property.

Our last step is to download the file GHUnitIOSTestMain.m and add it to our Test Classes group. Make sure you actually copy the file into the folder when you add it, we need this file to be a part of our directory structure for use in the template.


xcptStep2g.pngWe are now ready to run our application tests. Change the active target to TemplateBaseTests, switch to the Simulator, and run the target. If everything is configured properly, your test application should start. Click the Run button, and you should see something similar to this:

Once you have the TemplateBaseTests target running correctly, double check your dependencies by doing a clean, build, and run on the TemplateBaseTests target.

3. Add OCMock to the application test target

Now that our appplication test target works, we want to add support for OCMock. Something changed in Xcode since 3.2.3 and older methods of integrating OCMock appear to have quit working. I have talked with developers who struggled with getting it working and gave up, but I have not had any problems with the method I use.

The method that works consistently for me is to add the OCMock.framework and the libOCMock.a to our test target, with one caveat: the library file that is part of the normal OCMock distribution does not work with iPhone projects, we need the library file that is part of the iPhone example project.


xcptStep3a.pngFirst, download the standard installation file, ocmock-1.70.dmg and open it in Finder. Drag the OCMock.framework from the Release folder to the Frameworks group in your project. As with the GHUnit framework make sure you:

  • Check “Copy items into destination group’s folder (if needed)”
  • Uncheck TemplateBase in the Add to Targets window,
  • Check TemplateBaseTests in the Add to Targets window

The library file in the dmg file will not work with your iPhone project, so we need the one from the iPhone example project. Download the file libOCMock.a from the example project page, open it in Finder, and drag it to the Frameworks group in your project. As with the frameworks, make sure to copy the file, and include it in the TemplateBaseTests target.

Now we need to add some test cases that use OCMock to our SampleTestCase. Replace the entire contents of the SampleTestCase.m with the following code:

#import <GHUnit/GHUnit.h>
#import <OCMock/OCMock.h>

@interface SampleLibTest : GHTestCase { }
@end

@implementation SampleLibTest

- (void)testSimplePass {
    // Another test
}

- (void)testSimpleFail {
    GHAssertTrue(NO, nil);
}

// simple test to ensure building, linking, and running test case works in the project
- (void)testOCMockPass {
    id mock = [OCMockObject mockForClass:NSString.class];
    [[[mock stub] andReturn:@"mocktest"] lowercaseString];

    NSString *returnValue = [mock lowercaseString];
    GHAssertEqualObjects(@"mocktest", returnValue, @"Should have returned the expected string.");
}

- (void)testOCMockFail {
    id mock = [OCMockObject mockForClass:NSString.class];
    [[[mock stub] andReturn:@"mocktest"] lowercaseString];

    NSString *returnValue = [mock lowercaseString];
    GHAssertEqualObjects(@"thisIsTheWrongValueToCheck", returnValue, @"Should have returned the expected string.");
}

@end


xcptStep3b.pngWe are now ready to run our application tests. Change the active target to TemplateBaseTests, switch to the Simulator, and run the target. If everything is configured properly, your test application should start. Click the Run button, and you should see something similar to this:

Once you have the TemplateBaseTests target running correctly, double check your dependencies by doing a clean, build, and run on the TemplateBaseTests target.

4. Create an Xcode project template from the project

Creating a basic Xcode project template from your project requires some simple steps:

  1. Copying the project’s directory structure to the right place
  2. Renaming some files
  3. Changing references to your base project name in all the files in the project

Xcode looks for project templates in multiple locations, but the best place to put your new template is in the directory:

~/Library/Application Support/Developer/Shared/Xcode/Project Templates/Application

By placing your template here, future Xcode upgrades should leave it alone.

If this directory does not exist, go ahead and create it. Copy your project directory “~/xcpt/TemplateBase” into this directory. The name of the directory is the name that Xcode will use when it displays it under “User Templates”, so you can rename the top level directory name to whatever you want displayed.

One minor cleanup item at this point is to remove the files “username.pbxuser” and “username.perspective3″ from the TemplateBase.xcodeproj directory. You only need the “project.pbxproj” file.

At this point if you open Xcode and select New Project from the menu, your template will display in the list, and will even be usable. But, we do not want our new project to use file names like “TemplateBaseAppDelegate”, we want the file names to match whatever our new project name is, so we need to use the special file naming and tagging conventions that Apple uses in its templates.

There is a good post on CocoaDev that lists the available tags. When creating a new project, Xcode will do the appropriate text substitution in file names and contents based on these tags. Apple’s current style is to use three underscores “___” as delimiters. The CocoaDev post uses the older style of delimiters («tagname»), but the names are still the same.

For our example, we will only use two tags: “___PROJECTNAME___” and “___PROJECTNAMEASIDENTIFIER___”.

We cannot use Xcode to edit names since we will be changing contents of the internal structure of an Xcode project. Use command line tools or whatever editor you have on hand. I like to use TextMate for this sort of thing since it allows me to open an entire directory as a group and make changes en masse.

Before we edit any file contents, we need to rename the files in our project template directory to use the appropriate tag name. In the ‘~/Library/Application Support/Developer/Shared/Xcode/Project Templates/Application/TemplateBase’ directory, rename these files:

Existing file New name
Classes/TemplateBaseAppDelegate.h Classes/___PROJECTNAMEASIDENTIFIER___AppDelegate.h
Classes/TemplateBaseAppDelegate.m Classes/___PROJECTNAMEASIDENTIFIER___AppDelegate.m
TemplateBase-Info.plist ___PROJECTNAMEASIDENTIFIER___-Info.plist
TemplateBase.xcodeproj ___PROJECTNAME___.xcodeproj
TemplateBase_Prefix.pch ___PROJECTNAMEASIDENTIFIER____Prefix.pch
TemplateBaseTests-Info.plist ___PROJECTNAMEASIDENTIFIER___Tests-Info.plist

At this point, if we created a project from this template, it would be broken — our filenames would be inconsistent with the internal references to those files, so we now need to edit all the references to use tag names as well. These files all contain the string “TemplateBase” and need to be edited.

  • Classes/___PROJECTNAMEASIDENTIFIER___AppDelegate.h
  • Classes/___PROJECTNAMEASIDENTIFIER___AppDelegate.m
  • Classes/FirstViewController.h
  • Classes/FirstViewController.m
  • FirstView.xib
  • MainWindow.xib
  • SecondView.xib
  • ___PROJECTNAME___.xcodeproj/project.pbxproj
  • ___PROJECTNAMEASIDENTIFIER____Prefix.pch
  • main.m


xcptStep4b.pngI will use TextMate in my instructions, but any editor should do. Just make sure you don’t miss a file.

Open the top level directory for your template using TextMate. Evidently TextMate recognizes the framework and Xcode project file directories, so it does not add them by default. We need to add just the Xcode project file directory to our list by opening it up specifically inside this TextMate session. Right click on the empty space below the existing file names, select “Add Existing Files”, then select the directory name “___PROJECTNAME___.xcodeproj”.

Now do a global find and replace, changing all references of “TemplateBase” to “___PROJECTNAMEASIDENTIFIER___”. Save your changes, and your project template should be complete.

You should now be able to create a new project based on this template. Run both the application and test targets in the simulator on your newly created project to verify that.

Other Links

I have kept the instructions pretty minimal in this example, but there are obviously a lot of additional things you can do. Here are several links I found useful while working with GHUnit, OCMock, and Xcode project templates. If you had any problems with my example, perhaps one of these links will help you better!

Zip files of Project Templates

GHUnit

OCMock

Xcode Project Templates


We all need the support of others to do our best work. Find other like-minded developers that will provide encouragement and motivation through local user groups, conferences or meetups. I regularly attend Cocoa/iPhone developer meetups in Cincinnati, Ohio and Columbus, Ohio. If you are in the central or southwest Ohio area, come join me at either monthly meetup:

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!

Animating Multiple Virtual Pages Using a NIB-based View

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

Today’s post is a simplified version of some work I’m doing for a client.

For the client app, I need to browse a set of data using a NIB-based view, but do so by swiping left and right in the context of a parent view — a similar effect as Apple’s weather utility app. I didn’t explore how Apple actually does it, but the method I am using is pretty straightforward.

Overview

Demo2010Dec19_pic1.pngThis simple app displays a view for a single item at a time from an ordered list of simple domain objects. A UISwipeGestureRecognizer detects swipe events which are used to animate items on and off the parent view.

The previous view is off screen to the left, and the next view is off screen to the right. Both of these are preloaded so that when a swipe event is recognized, there is no delay while loading data for the item to be animated onto the parent view. The app cycles through three instances of the same NIB-based view controller as the user swipes.

For instance, given a list of 7 items, the app starts in this state:

  • The center view displays item A;
  • The view off screen to the right is preloaded with item B;
  • The view off screen to the left is preloaded with the last item, item G;

In this state, when a left swipe event is recognized, I want it to be interpreted as “move the currently displayed item (A) to the left and show me the next item (B)”. What happens is this:

  • The position of the center view is animated to the left off screen position;
  • The position of the right view is animated to the center on screen position;
  • The old center view becomes the new left view;
  • The old right view becomes the new center view;
  • Since the old left view is “pushed” farther to the left, it becomes the new right view;
  • The new right view is loaded with the appropriate data from the list.

A mirrored set of events happens on a right swipe event. (The app treats the list circularly, so there is no right or left edge of items.) The app also includes a tap recognizer which is used to update the tap count for each item to demonstrate how you can maintain state as views are cycled.

Handling Gestures

Each instance of SampleViewController has three gesture recognizers, swipe left, swipe right, and tap. Each also retains a reference to it’s currently displayed item when it is loaded.

The behavior for tapping is simple. When a tap is recognized on a view, the tap count for that view’s item is updated. Nothing needs to happen outside the current view and item.

The behavior for swiping is slightly more involved. Since a swipe is supposed to initiate animating the current view off the screen and a new view into the center, it would be messy for the current view to handle the animation. The best solution is to have the parent view handle the animation, since it already owns all the items and views necessary.

The cleanest way to accomplish this is by creating a simple protocol for delegating the behavior. SampleViewController.h includes the protocol definition, and adds an ivar for the delegate itself.

SampleViewController.h

#import <UIKit/UIKit.h>
#import "SampleData.h"

@class SampleViewController;

@protocol SampleViewControllerDelegate
- (void) handleSwipeLeftFrom:(SampleViewController *) source;
- (void) handleSwipeRightFrom:(SampleViewController *) source;
@end

@interface SampleViewController : UIViewController {
    UILabel *sampleIdLabel;
    UILabel *nameLabel;
    UILabel *tapCountLabel;
    UIImageView *imageView;

    SampleData *sampleData;

    id<SampleViewControllerDelegate> delegate;

    UISwipeGestureRecognizer *swipeLeftRecognizer;
    UISwipeGestureRecognizer *swipeRightRecognizer;
    UITapGestureRecognizer *tapRecognizer;
}

@property (nonatomic, retain) IBOutlet UILabel *sampleIdLabel;
@property (nonatomic, retain) IBOutlet UILabel *nameLabel;
@property (nonatomic, retain) IBOutlet UILabel *tapCountLabel;
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) SampleData *sampleData;
@property (nonatomic, retain) id<SampleViewControllerDelegate> delegate;

- (void) loadSampleData:(SampleData *) aSampleData;

@end

and in the implementation simply forwards to the appropriate method of the delegate:

SampleViewController.m snippet

- (void)handleSwipeLeftFrom:(UISwipeGestureRecognizer *)recognizer {
    [delegate handleSwipeLeftFrom:self];
}

- (void)handleSwipeRightFrom:(UISwipeGestureRecognizer *)recognizer {
    [delegate handleSwipeRightFrom:self];
}

- (void)handleTap:(UITapGestureRecognizer *)recognizer {
    self.sampleData.tapCount += 1;
    [self updateTapCountLabel];
}

The delegate owns the three instances of SampleViewController, so is able to properly manage the animation between views:

Demo2010Dec19ViewController snippet (SampleViewControllerDelegate implementation)

- (void) handleSwipeLeftFrom:(SampleViewController *) source {
    if (source == centerSVC) {
        [UIView animateWithDuration:SLIDE_DURATION
                         animations:^{
                             centerSVC.view.frame = leftFrame;
                             rightSVC.view.frame = centerFrame;
                         }];

        // move untouched view to other side, and adjust names for next cycle
        leftSVC.view.frame = rightFrame;
        SampleViewController *tempSVC = centerSVC;
        centerSVC = rightSVC;
        rightSVC = leftSVC;
        leftSVC = tempSVC;

        // cache next sample
        currentIdx = [self checkIdx:currentIdx+1];
        int rightIdx = [self checkIdx:currentIdx+1];
        [rightSVC loadSampleData:[samples objectAtIndex:rightIdx]];
    }
}

More to be done

There is much that can easily be done to enhance this example, some of which I will be adding to my client’s app. Things like:

  • Adding a UIPageControl at bottom
  • Adding fade-in/fade-out toolbars for extra navigation (like the Kindle App)
  • Implementing momentum on swiping so fast swiping moves past multiple views

Hopefully this helps someone get over the hurdle of animating between sibling views. I know I made several simplifications to my original code while preparing the sample code for this blog.

You may download the sample project and use the code however you wish.

Merry Christmas!!

I wish all of you a very Merry Christmas.

Make sure you take time to relax with family and friends this week, but also take some time to read and consider the original Christmas story.


We all need the support of others to do our best. Find other like-minded developers that will provide encouragement and motivation through local user groups, regular conferences or meetups. This post is part of iDevBlogADay which has really helped me stay on track with my writing and my iOS projects.

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!

Open Source iOS CoverFlow Implementations

Filed in iDevBlogADay, iOS Development | Comments Off |

For my personal iOS development, I have a technical experiment and exploration todo list. It includes techniques I need to get better at, open source packages to investigate, that sort of thing.

I try to keep the items on the list small enough to do enough prototyping in a single evening to satisfy my curiosity. That way I am willing to move on during my next exploration session. The point is not usually proficiency, but enough familiarity to decide if the technique or framework merits further study. I often keep the code around as a reference, but it is definitely throwaway code, so it’s in a separate folder than “real” code.

One of the items on my list was to find and investigate CoverFlow clone examples floating around the intertubes. I found several that were based on Apple’s private APIs or were old enough that I was not interested. But, I did find two that I spent some time investigating.

OpenFlow, a CoverFlow clone developed during iPhoneDevCamp

The first was OpenFlow by Alex Fajkowski, released at iPhoneDevCamp in August, 2009. It is hosted on GitHub, but it does not look like it has been updated since then.

There is sample code included with the OpenFlow download, but it does not have a simple, quick-start example to get an initial feel for the package. Fortunately, others have written posts with some simple examples, two I looked at were:

A simple example by Julios Barros’ (@juliobarros).

And another simple example, but with more pictures and step-by-step details.

I liked OpenFlow well enough, but the current implementation did not allow for flicking through multiple covers. It behaves a little more like iTunes on the mac, not like browsing albums on the iPhone iPod app. Fortunately, my other “find” did have better flicking behavior, with tweakable momentum settings.

FlowCover, an easy to use OpenGL ES based CoverFlow clone

My other “find”, FlowCover by William Woody is essentially one OpenGL ES class with a simple helper class for data caching.

I like simple. Since I am likely to tweak the behavior of whatever I find, the simpler and cleaner the starting point — the better.

I added the two classes to my prototyping base project, and I was off and running. FlowCover works pretty much as expected, behaving smoothly and simply. The only change I made to FlowCover.m was to allow for different scaling when in landscape and portrait modes. Other than that, it worked just as I wanted.

Conclusion

If you are interested in adding some Cover Flow type behavior to your app, I recommend checking out both projects.

OpenFlow is based on UIKit, and has more features than FlowCover.

FlowCover is based on OpenGL ES, has few features, but behaves a little more like I expected Cover Flow on an iPhone to behave.

Either is a good choice, but my needs are simple enough right now that I think I will be using FlowCover.


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, many of them are either developers associated with iDevBlogADay, or those I have met through the 360iDev conferences. I also 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 one other 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!

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!

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!