The classic C-style for loop
The C-style for (initializer; condition; increment) loop is fully available in Objective-C and remains common for index-based iteration, such as reversing a mutable array in place or iterating a fixed number of times when you need the index itself (for example to compute a running offset into a buffer). Each of the three clauses is optional, so for (;;) { } is a valid, if unusual, infinite loop.
Cricket analogy: Counting down the final over ball by ball with for (int ball = 1; ball <= 6; ball++) mirrors exactly how a scorer tracks each delivery of an over, needing the index to announce 'this is ball four.'
Fast enumeration with for-in
Fast enumeration, written as for (id object in collection), is the idiomatic way to iterate NSArray, NSSet, NSDictionary (iterating keys), and any class conforming to NSFastEnumeration. It's both more concise and typically faster than manual indexing because it uses countByEnumeratingWithState:objects:count: under the hood to batch-retrieve objects, avoiding the overhead of repeated objectAtIndex: message sends.
Cricket analogy: Fast enumeration is like a fielding coach walking straight down the list of eleven players calling out names, rather than looking up each player by jersey number one at a time — faster and more direct.
You cannot mutate a collection (add or remove objects) while fast-enumerating it with for-in; doing so throws an NSGenericException at runtime ('*** Collection <...> was mutated while being enumerated'). To modify while iterating, either iterate over a copy or collect changes and apply them after the loop.
while and do-while loops
A while loop checks its condition before each iteration and may run zero times, whereas a do-while loop checks after the body executes, guaranteeing at least one pass — useful for patterns like retry logic where you always want to attempt an operation once before checking whether to retry. Both are common in Objective-C for condition-driven iteration where the number of iterations isn't known in advance, such as reading bytes from an NSInputStream until it reports no more data.
Cricket analogy: A while loop is like bowling overs 'while there are wickets in hand and overs remaining' — you might not bowl at all if the innings is already over, unlike a do-while that always sends down at least one ball.
break and continue
break exits the innermost enclosing loop (or switch) immediately, while continue skips the rest of the current iteration's body and jumps to the loop's next condition check or increment step. In fast enumeration, both keywords work the same way as in a for or while loop, making it easy to write early-exit search logic, such as breaking out of a for-in loop the moment a matching object is found.
Cricket analogy: A break when a batter is dismissed ends that innings segment immediately, while continue on a wide ball skips scoring but the same batter carries on facing the next delivery.
NSArray<NSString *> *names = @[@"Ada", @"Grace", @"Alan", @"Margaret"];
// Fast enumeration with early exit
NSString *foundName = nil;
for (NSString *name in names) {
if ([name hasPrefix:@"A"]) {
foundName = name;
break;
}
}
NSLog(@"First A-name: %@", foundName);
// Classic for loop with continue
for (NSInteger i = 0; i < names.count; i++) {
if (names[i].length < 4) {
continue; // skip short names
}
NSLog(@"Long name at index %ld: %@", (long)i, names[i]);
}
// do-while retry pattern
NSInteger attempts = 0;
BOOL success = NO;
do {
attempts++;
success = [self attemptConnection];
} while (!success && attempts < 3);NSEnumerator (obtained via reverseObjectEnumerator, objectEnumerator, etc.) offers manual, pull-based iteration with nextObject when you need to pause enumeration mid-loop or iterate in reverse without indices.
- The classic for loop is best when you need the numeric index during iteration.
- for-in (fast enumeration) is the idiomatic, faster way to iterate NSArray, NSSet, and NSDictionary.
- Mutating a collection during fast enumeration throws an NSGenericException at runtime.
- while checks its condition before the loop body and may execute zero times.
- do-while checks after the body, guaranteeing at least one execution — useful for retry logic.
- break exits the innermost loop immediately; continue skips to the next iteration.
- NSEnumerator provides manual, pull-based iteration as an alternative to for-in.
Practice what you learned
1. Which loop construct guarantees the loop body executes at least once?
2. What happens if you add an object to an NSMutableArray while fast-enumerating it with for-in?
3. What is the primary advantage of for-in over a manual indexed for loop for NSArray?
4. Inside a nested loop, what does break do?
5. Which protocol must a custom class conform to in order to support for-in iteration?
Was this page helpful?
You May Also Like
Conditionals in Objective-C
Learn how Objective-C branches program flow using if/else, the ternary operator, and switch statements, and how BOOL and nil interact with truthiness.
Methods and Message Passing
Explore how Objective-C methods work as messages sent to objects at runtime, including selectors, method signatures, and dynamic dispatch.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics