Friday, October 30, 2009

iPhone Friday - October 30, 2009

Hello and happy Friday.  Today's collection of iPhone and iPod touch wallpapers is the second part of a two part series entitled Bubble Series A; five pictures of bubbles taken at night.  Enjoy.










Thursday, October 29, 2009

iPhone Tech Talk World Tour 2009

We're attending Apple's iPhone Tech Talk World Tour 2009 in Santa Clara today. I went to last year's event and I highly recommend it. It's open to registered Apple iPhone developers only, but it's free and you get free breakfast and lunch and a t-shirt. And the talks are great too :-).

Tuesday, October 27, 2009

Tales of App Store Failure

Sean Maher, the creator of the iPhone zombie game Dead Panic, shares his sales figures and writes about the difficulty of building a sustainable business in Tales of App Store Failure.

Objective-C Tuesdays: the while loop

After the standard C for loop and the Objective-C 2.0 for...in loop, the while loop is the most common. Unlike the full-featured for loop and the specialized for...in loop, the while is simpler and more free-form.

The while loop starts with the keyword while followed by parentheses containing the condition. After the parentheses, a single statement or block makes up the body of the loop.
/* while loop with a single statement */
while (condition) statement;

/* while loop with a block */
while (condition)
{
  block;
}
Watch out for a hard to spot bug when the while loop is followed by an empty statement created by an extra semicolon:
while (condition); /* <-- warning! empty statement! */
{
  /* this block is not part of the loop */
  /* it's always executed exactly once  */
}
The condition in a while loop is evaluated before the body of the loop is executed, so you can create loops that execute zero or more times. If you want the body of the loop to execute one or more times, you can use a do...while loop instead.

The initialization of the loop counter or other loop variables must be done before the while loop statement; often this means declaring and initializing a local variable:
int i = 0;
while (i < 10)
When using a loop counter, it is important to remember to advance the counter to the next value in the body of the loop. For instance, to log the numbers 0 through 9:
int i = 0;
while (i < 10) {
  NSLog(@"%d", i);
  i++; /* advance the loop counter */
}
If you forget to advance the loop counter, you will create an infinite loop.
int i = 0;
/* warning, infinite loop, i is always 0 */
while (i < 10) {
  NSLog(@"%d", i);
  /* oops, forgot to increment i */
}
The while loop is frequently used when iterating over a stream or sequence of unknown size where a loop counter is unnecessary. For instance, to iterate over a null-terminated string by incrementing the string pointer:
char const *s = "foobar";
while (*s) {        /* while current character isn't zero */
  NSLog(@"%c", *s); /* log the current character */
  s++;              /* increment address in s to next character */
}
Similarly, the idiomatic way to read characters from a standard C FILE is:
FILE *file = /* open file for reading ... */;
int ch;
while ( (ch = fgetc(file)) != EOF) {
  NSLog(@"%c", ch);
}
The loop condition ( (ch = fgetc(file)) != EOF) in this idiom does three things:
  1. fgetc(file) gets the current character and advances to the next
  2. (ch = fgetc(file)) assigns the current character to ch
  3. (ch = ...) != EOF checks that the value of ch is not EOF
Next time, we will look at the do...while loop.

Friday, October 23, 2009

iPhone Friday - October 23, 2009

Hello and happy Friday.  Today's collection of iPhone and iPod touch wallpapers are from a two part series entitled Bubble Series A.  Today we have part one - five pictures of bubbles taken at night.  Enjoy.










Wednesday, October 21, 2009

Dear Palm, it's just not working out.

Jamie Zawinski has recently been writing about his travails trying to publish some open source applications for the Palm Pre. As iPhone developers who have to deal with Apple's often opaque and sometimes arbitrary approval process, we certainly sympathize.

On Monday he publicly declared that he's giving up on the Pre and buying an iPhone. And his beef is not with Palm's app approval process, but with the Pre itself:
Believe it or not, this actually has nothing to do with my utterly nightmarish experience of trying to get my applications into Palm's app catalog, and everything to do with the fact that the phone is just a constant pain to use.
He goes on to praise the iPhone:
and even though I absolutely despise the iPhone's on-screen keyboard... at least now I have a phone whose software actually works.
Jamie's post also inspired Steve Frank of Panic to write about his love-hate relationship with the iPhone.

Read Dear Palm, it's just not working out.

Tuesday, October 20, 2009

Objective-C Tuesdays: The for...in loop

We've looked at the standard for loop for the last two weeks. This week we will dive into the for...in loop introduced in Objective-C 2.0. Unlike the standard for loop, the for...in loop is not available in plain old C.

In Objective-C, collection classes such as NSArray, NSSet and NSDictionary are a key part of the Objective-C Foundation framework. Collections provide high level ways to group and organize objects.

In older versions of Objective-C, looping over items in a collection is done using an NSEnumerator object in a while loop:
NSSet *items = [NSSet setWithObjects:@"foo", @"bar", nil];
NSEnumerator *enumerator = [items objectEnumerator];
NSString *item = nil;
while (item = [enumerator nextObject]) {
  // do something with item
}
It's possible to loop over items in a NSArray using a standard for loop, since NSArray has a well defined order:
NSArray *items = [NSArray arrayWithObjects:@"foo", @"bar", nil];
for (NSUInteger i = 0; i < [items count]; i++) {
  NSString *item = [items objectAtIndex:i];
  // do something with item
}
Unfortunately, some collection classes (such as NSSet) don't have a well defined order; NSEnumerator used to be the only option.

The for...in loop works on any collection that conforms to the NSFastEnumeration protocol (all the standard ones do). The for...in loop is similar to a standard for loop but simpler. Instead of the three sections of a standard for loop, there are two, the loop variable and the collection expression:
for (loop variable in collection expression) {
  // do something with loop variable
}
Loop Variable The loop variable can be a previous declared variable:
NSString *item = nil;
// ...
for (item in collection expression) {
  // do something with item
}
or it can be declared inside the parentheses:
for (NSString *item in collection expression) {
  // do something with item
}
Collection Expression The collection expression can be any expression that evaluates to an object conforming to NSFastEnumeration. Typically, this is simply a collection variable defined elsewhere:
NSSet *items = [NSSet setWithObjects:@"foo", @"bar", nil];
// ...
for (NSString *item in items) {
  // do something with item
}
but can be a function call or method call:
for (NSString *item in [NSSet setWithObjects:@"foo", @"bar", nil]) {
  // do something with item
}
Dictionaries When using a for...in loop with a NSDictionary, the loop variable receives the dictionary keys; to work with the dictionary values inside the loop, use objectForKey:
NSDictionary *numbers = [NSDictionary dictionaryWithObjectsAndKeys:
    @"zero", @"0", 
    @"one", @"1", 
    nil];
for (NSString *key in numbers) {
  NSString *value = [numbers objectForKey:key];
  // do something with key and value
}
Mutation Guard Modifying a collection while iterating over it can cause very unintuitive behavior, so the for...in loop uses a mutation guard behind the scenes. If items are added or removed from a collection while your for...in loop is running, an exception is thrown. This is generally a good thing, but it makes filtering a collection somewhat tricky:
NSMutableSet *items = [NSMutableSet setWithObjects:@"", @"a", @"aa", @"aaa", nil];
for (NSString *item in items) {
  if (item.length < 2) {
    [items removeObject:item]; // WARNING: exception thrown on mutation
  }
}
The way to get around this restriction is to iterate over a copy of the collection and modify the original (or vice versa):
NSMutableSet *items = [NSMutableSet setWithObjects:@"", @"a", @"aa", @"aaa", nil];
for (NSString *item in [[items copy] autorelease]) {
  if (item.length < 2) {
    [items removeObject:item]; // OKAY: looping over copy, changing original
  }
}
Next week, we will look at the while loop.