Reputation: 1204
I want to break out of a loop that's being enumerated.
Here's an example of my problem:
for(NSArray *x in retrieved_data){
for(NSDictionary *someJson in array_that_is_enumerated){
if(intersection_of_retrieved_data_indicates_deletion_in_array){
[array_that_is_being_enumerated removeObject:someJson];
// can't call return; here: it's important outer for loop finishes.
// break; will only have effect in this scope
} else {// perform other logic}
}
}
How can I still delete this object and jump to the first for/in
loop again?
Upvotes: 0
Views: 90
Reputation: 53000
A break
terminates the closest enclosing loop, so a break
in your if
moves to the next iteration of your outer loop, which from:
can't call return; here: it's important outer for loop finishes
appears to be exactly what you want.
Terminating multiple nested loops can be messy, you can do things like: use a label and goto
; set a flag to test in each loop; or wrap the loops in a function/method/block and return
.
HTH
Addendum
There appears to be some concern in comments/answers about deleting while enumerating, while this is completely correct you can delete within an enumerating loop provided you then terminate the loop - it is proceeding to the next iteration which is not allowed. So what the OP is doing, a test-delete-break, is perfectly OK.
After Comment
Following on from addendum, here is some sample code:
NSArray *outer = @[@"one", @"three", @"dog"];
NSMutableArray *inner = @[@"one", @"two", @"cat", @"dog"].mutableCopy;
NSLog(@"Before: %@", inner);
for (NSString *wordToDelete in outer)
{
NSLog(@"Consider: %@", wordToDelete);
for (NSString *item in inner)
{
if ([item isEqualToString:wordToDelete])
{
NSLog(@"Removing and breaking");
[inner removeObject:item];
break;
}
}
// break lands here
}
NSLog(@"After: %@", inner);
The final result is @[ @"two", @"cat" ]
. The inner loop terminates and the outer one completes. It is legitimate to do this, what would be incorrect would be doing an iteration after inner
was modified.
Upvotes: 2
Reputation: 62686
I think you can get what you want without break
. It seems the job of that inner loop is to identify elements in array_that_is_enumerated that should be deleted, and that decision depends on the elements in retrieved_data.
@Agressor is right that you cannot delete while enumerating, so how about isolating the deletion condition in a function?
// this could be done neatly as an NSPredicate, too
- (NSDictionary *)itemInInnerArrayThatShouldBeDeleted:(NSArray *)xFromRetrievedData {
for (NSDictionary *someJson in array_that_is_enumerated) {
if (intersection_of_retrieved_data_indicates_deletion_in_array) {
return someJson;
}
}
return nil;
}
Now your outer loop collects elements to be deleted as follows:
NSMutableArray *deleteThese = [NSMutableArray array];
for (NSArray *x in retrieved_data) {
NSDictionary *someJson = [self itemInInnerArrayThatShouldBeDeleted:x];
if (someJson) [deleteThese addObject:someJson];
}
// now that we are done enumerating, we can safely delete
[array_that_is_enumerated removeObjectsInArray:deleteThese];
Upvotes: 0