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
See Also
Looping in Objective-C
Last week we looked at how to end a loop early using the Looping in Objective-C
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
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
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:
You can use a boolean flag variable to indicate when you're done:
You can use
Next week we will look at the other loop flow modifier,
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 } // AThe 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.
Tuesday, November 10, 2009
Objective-C Tuesdays: the do...while loop
Last time we looked at the
Unlike the
The
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.
Subscribe to:
Posts (Atom)