Consider the following image:

My app first finds all the blue pixels and also records the x,y coordinates of all their siblings (the siblings for a given pixel are those that border it: up, down, left, right, upper-left, upper-right, etc). It then loops through all of these blue pixels in order to figure out how many blue siblings they have. The goal is ultimately to determine which group of blue pixels is the biggest.
This is a large loop, though, and it ends up resulting in the error “warning: Unable to restore previously selected frame.” I believe this occurs because I’m overflowing the stack. If that is the case, how would you recommend I change my code in order to fix this issue?
Here’s the code:
The method that starts the looping:
for (NSString *key in pixelItemDict) {
Pixel *px = [pixelItemDict objectForKey:key];
if (!px.hasBeenCounted) {
//If it hasn't been counted, we know that we're onto a new distinct area, because otherwise counterForSiblingsOfPixel would have already counted it. So we now add a copy of the pixelsCurrentlyBeingCounted array, empty that array, and reset the counter
[pixelCounterDict setObject:[pixelsCurrentlyBeingCounted copy] forKey:[NSString stringWithFormat:@"%i",currentPxCounter]];
[pixelsCurrentlyBeingCounted removeAllObjects];
[self counterForSiblingsOfPixel:px];
}
}
The method that continuously calls itself, resulting in the stack overflow:
- (void)counterForSiblingsOfPixel:(Pixel *)px
{
[pixelsCurrentlyBeingCounted addObject:px];
currentPxCounter++;
px.hasBeenCounted = true;
for (Pixel *sibling in px.siblings) {
if (!sibling.hasBeenCounted) [self counterForSiblingsOfPixel:px];
}
}
Essentially, I have a pixelItemDict that contains all the blue pixels. I enumerate over this dictionary, calling the method counterForSiblingsOfPixel: on each one. That method in turn calls itself on each one of the siblings of the pixel passed to it. The forin loop only regains control once every pixel in an area of blue has been counted. Therefore, large areas of blue result in counterForSiblingsOfPixel: calling itself a huge number of times, leading to the overflow.
Is there a standard design pattern that should be used in cases such as this?
First, you’re not modifying
px, so each call to-counterForSiblingsOfPixel:will do exactly the same thing. When you use recursion, you want to make sure that each level of recursion simplifies the problem to some degree. If the recursion doesn’t eventually hit some base case, it’ll go on forever and, yes, overflow the stack. So, start by making sure that your call to that method is for some simpler case.Second, you probably don’t want to simplify by just one pixel… You’d be fine if this method divides the pixels into two halves and calls itself recursively for each half, because you’d only end up with log2(pixels) levels of recursions — about 20 for a millions pixels. But if you process one pixel and then call yourself recursively for the remaining pixels, you’d end up with 1000000 levels of recursion, which will also overflow.