Friday, November 27, 2009

iPhone Friday - November 27, 2009

Hello and Happy Gobble Gobble!  I hope you all are recovering nicely from your tryptophan enduced food coma.  Sorry for being late on this iPhone Friday as I too was feeling lethargic from a days worth of eating.  So today I am posting the iPhone and iPod touch wallpapers - they are - sublime...  Enjoy!








Tuesday, November 24, 2009

Objective-C Tuesdays: continue

Last week we looked at how to end a loop early using the break keyword. Today we will look at a similar action: how to skip to the next iteration.

Sometimes you need to process each item in a collection or sequence, but some of those items get full processing and some don't. For example, you may want to skip empty strings in a collection. Frequently you do this using an if...else statement:
NSArray *collection = [NSArray arrayWithObjects: @"foo", @"", @"bar", @"baz", @"", nil];
int wordCount = 0;
for (NSString *item in collection) {
  NSLog(@"found '%@'", item);
  if (item.length > 0) {
    wordCount++;
  }
}
NSLog(@"word count = %d", wordCount);
This is generally a good approach, but sometimes you have complex nested logic:
NSArray *collection = [NSArray arrayWithObjects: @"foo", @"\n", @"bar", @"baz", @"", nil];
int wordCount = 0;
for (NSString *item in collection) {
  NSLog(@"found '%@'", item);
  if (item.length > 0) {
    if ( ! [item isEqualToString:@"\n"]) {
      wordCount++;
      if (item.length < 4) {
        NSLog(@"short word");
      } else {
        NSLog(@"long word");
      }
    }
  }
}
NSLog(@"word count = %d", wordCount);
The continue statement can help you simplify complicated cases like this by stopping the execution of the loop body for the current item and advancing to the next. Using continue, we can rewrite the example like this:
NSArray *collection = [NSArray arrayWithObjects: @"foo", @"\n", @"bar", @"baz", @"", nil];
int wordCount = 0;
for (NSString *item in collection) {
  NSLog(@"found '%@'", item);
  if (item.length > 0) continue;
  if ([@item isEqualToString:"\n"]) continue;

  wordCount++;
  if (item.length < 4) {
    NSLog(@"short word");
  } else {
    NSLog(@"long word");
  }
}
NSLog(@"word count = %d", wordCount);
Like break, a continue statement only works on the innermost loop that encloses it:
// outer loop
for (int i = 0; i < 10; i++) { // loop A
  if (...) continue; // skips to next item in A
  
  // inner loop
  for (int j = 0; j < 10; j++) { // loop B
    if (...) continue; // skips to next item in B
  }
  
  if (...) continue; // skips to next item in A
  
}
The continue statement is most useful with a for or for...in loop, but can be used with a while and do...while loop with care. It's easy to create an infinite while loop using continue:
NSArray *collection = [NSArray arrayWithObjects: @"foo", @"", @"bar", @"baz", @"", nil];
int wordCount = 0;
int i = 0;
while (i < collection.count) {
  NSString *item = [collection objectAtIndex:i];
  NSLog(@"found '%@'", item);
  if (item.length > 0) {
    continue; // OOPS! forgot to increment i
  }

  wordCount++;
  i++;
}
NSLog(@"word count = %d", wordCount);
This loop will reach the second item in the collection and get stuck there -- it never reaches the i++ at the end of the loop body. The solution is simple:
NSArray *collection = [NSArray arrayWithObjects: @"foo", @"", @"bar", @"baz", @"", nil];
int wordCount = 0;
int i = 0;
while (i < collection.count) {
  NSString *item = [collection objectAtIndex:i];
  NSLog(@"found '%@'", item);
  if (item.length > 0) {
    i++;;  // move to next item
    continue;
  }

  wordCount++;
  i++;
}
NSLog(@"word count = %d", wordCount);
This is a consequence of the free-form nature of the while and do...while loops. The compiler knows how to make a for or for...in loop advance to the next item, but the other loops leave that up to you; continue acts more like a special goto statement with while and do...while loops.

Next time, we'll look at the mother of all loops, the goto statement.

Friday, November 20, 2009

iPhone Friday - November 20, 2009

Happy iPhone Friday. Today we are taking a break from the Guilloche series and pushing up a few iPhone, iPod touch (and Pre - shhhhh), wallpapers that are autumn inspired. Enjoy.








Tuesday, November 17, 2009

Objective-C Tuesdays: break out of a loop

Last week we finished looking at the four looping statements in Objective-C: the for loop, the Objective-C 2.0 for...in loop, the while loop and the do...while loop. Today we'll look at how you break out of a loop early.

Sometimes you want to stop a loop prematurely. A common example of this is when you need to iterate over an unsorted collection or array looking for an item:
NSArray *collection = [NSArray arrayWithObjects:@"foo", @"a", @"bar", @"baz", @"b", nil];
for (NSUInteger i = 0; i < collection.count; i++) {
  NSString *item = [collection objectAtIndex:i];
  NSLog(@"Checking item '%@'", item);
  if (item.length == 1) {
    NSLog(@"Found single letter at index %u", i);
    /* no need to look at the rest -- we can stop now */
  }
}
Once you find the item you're looking for, there's no need to finish the loop. In fact, if you search the whole collection, you will always find the last item that matches your criteria, which isn't always what you want.

You can use a boolean flag variable to indicate when you're done:
NSArray *collection = [NSArray arrayWithObjects:@"foo", @"a", @"bar", @"baz", @"b", nil];
BOOL foundFirst = NO;
for (NSUInteger i = 0; i < collection.count && ! foundFirst; i++) {
  NSString *item = [collection objectAtIndex:i];
  NSLog(@"Checking item '%@'", item);
  if (item.length == 1) {
    NSLog(@"Found first single letter at index %u", i);
    foundFirst = YES;
  }
}
This approach works, but is somewhat complicated and error-prone. A nicer way to exit a loop early is to use the break keyword. Using break, the example becomes:
NSArray *collection = [NSArray arrayWithObjects:@"foo", @"a", @"bar", @"baz", @"b", nil];
for (NSUInteger i = 0; i < collection.count; i++) {
  NSString *item = [collection objectAtIndex:i];
  NSLog(@"Checking item '%@'", item);
  if (item.length == 1) {
    NSLog(@"Found first single letter at index %u", i);
    break;
  }
}
When the break statement is encountered, loop processing is stopped and execution resumes with the first statement after the loop; you can think of break as a sort of return statement for loops.

You can use break to exit any of the loop statements. If we don't care about the index of the first item, we can simplify the example further by using the for...in loop:
NSArray *collection = [NSArray arrayWithObjects:@"foo", @"", @"bar", @"baz", @"", nil];
for (NSString *item in collection) {
  NSLog(@"Checking item '%@'", item);
  if (item.length == 1) {
    NSLog(@"Found first single letter");
    break;
  }
}
The break statement only works on the innermost loop that encloses it:
// outer loop
for (int i = 0; i < 10; i++) {
  if (...) break; // skips to A
  
  // inner loop
  for (int j = 0; j < 10; j++) {
    if (...) break; // skips to B
  }
  // B
  
}
// A
The first break statement is inside the outer loop, and will skip to A. The second break statement is inside the inner loop; it skips to B, ending the inner loop but staying inside the outer loop.

Next week we will look at the other loop flow modifier, continue statement.

Friday, November 13, 2009

iPhone Friday - November 13, 2009

Happy Friday (the 13th).  (^_^)  Today's collection continues last weeks Guilloche study.  Enjoy.







Tuesday, November 10, 2009

Objective-C Tuesdays: the do...while loop

Last time we looked at the while loop. Today we'll examine it's sibling the do...while loop.

Unlike the while loop, the do...while loop is guaranteed to execute the loop body at least once. The loop condition is checked at the end of each loop iteration.

The do...while loop starts with the keyword do followed by a single statement or block that makes up the body of the loop. The loop body is followed by the keyword while and parentheses containing the condition with a semicolon at the end.

The do...while loop is almost always written on three or more lines, and almost always with a block instead of a single statement.
/* do...while loop with a single statement */
do
  statement;
while (condition);

/* do...while loop with a block */
do {
  block;
} while (condition);
Initialization of the loop counter or other loop variables must be done before the do...while statement; this often means declaring and initializing a local variable:
int i = 0;
do {
  /* ... */
} while (i < 10);
When using a loop counter, it's 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;
do {
  NSLog(@"%d", i);
  i++; /* advance the loop counter */
} while (i < 10);
If you forget to advance the loop counter, you'll create an infinite loop.
int i = 0;
/* warning, infinite loop, i is always 0 */
do {
  NSLog(@"%d", i);
  /* oops, forgot to increment i */
} while (i < 10);
The key thing that differentiates the do...while loop from the while loop is that it always executes the loop body at least once; the while loop doesn't guarantee that. An example of this difference:
BOOL looping = NO;

NSLog(@"before while loop:");
while (looping) {
  NSLog(@"  executing the while loop");
}
NSLog(@"after while loop:");

NSLog(@"before do...while loop:");
do {
  NSLog(@"  executing the do...while loop");
} while (looping);
NSLog(@"after do...while loop:");
The output of these two loops looks like this:
before while loop:
after while loop:
before do...while loop:
  executing the do...while loop
after do...while loop:
Next week, we'll look at using break to break out of a loop.

Friday, November 6, 2009

iPhone Friday - November 6, 2009

Hello and happy Friday.  Today's iPhone and iPod touch wallpapers are from the Guilloche Study.  Enjoy.