0

So I'm building this iOS app. Everytime the use taps on a small square that square should change color. I've made sure that all my methods are defined. And I've changed the name of the xIndex value so that I can ENSURE that it isn't the view's .xIndex value that's the source of the crash. But no matter what I seem to do, I still seem to get:

'-[UIView xIndex]: unrecognized selector sent to instance 0x7fe06be6ce70'

Note that the above instance refers to the memory address of specificSquare. Any guesses? Been battling this for hours.

- (void)handleFunViewSquareTap:(UITapGestureRecognizer*)sender
{
    if (sender.state == UIGestureRecognizerStateEnded)
    {
        // handling code
        CGPoint locationOfTap = [sender locationInView: self.view];
        NSInteger xVIndex = floorf(locationOfTap.x / 40.f);
        NSInteger yIndex = floorf(locationOfTap.y / 40.f);

        // find the view that matches these indexes
        for(FunViewSquare *specificSquare in [self.view subviews])
        {
            if((specificSquare.xIndex == xVIndex) && (specificSquare.yIndex == yIndex))
           {
//                //specificSquare.backgroundColor = [ViewController randomColor];
           }
        }
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];

        CGRect frameRect = self.view.frame;
        NSInteger xIndex, yIndex = 0;
        for( CGFloat yPosition = 0.0; yPosition < frameRect.size.height; yPosition+=40.0f )
        {
            // reset xIndex on every iteration
            xIndex = 0;
            for( CGFloat xPosition = 0.0; xPosition < frameRect.size.width; xPosition+=40.0f )
            {
                FunViewSquare *randomSquare = [[FunViewSquare alloc] initWithFrame: CGRectMake(xPosition, yPosition, 40.f, 40.0f)];

                if(randomSquare)
                {
                    randomSquare.backgroundColor = [ViewController randomColor];
                    randomSquare.xIndex = xIndex;
                    randomSquare.yIndex = yIndex;
                    [self.view addSubview: randomSquare];
                }
                xIndex++;
            }
            yIndex++;
        }

        butGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleFunViewSquareTap:)];
        if(butGestureRecognizer)
        {
            [self.view addGestureRecognizer: butGestureRecognizer];
        }

}


+ (UIColor *)randomColor
{
    UIColor *colorToReturn;

    uint32_t randomNumber = random();
    randomNumber = (randomNumber % 10); // a random number between 0 & 10

    switch(randomNumber)
    {
        case 0 :
            colorToReturn = [UIColor blueColor];
            break;
        case 1 :
            colorToReturn = [UIColor grayColor];
            break;
        case 2 :
            colorToReturn = [UIColor greenColor];
            break;
        case 3 :
            colorToReturn = [UIColor purpleColor];
            break;
        case 4 :
            colorToReturn = [UIColor redColor];
            break;
        case 5 :
            colorToReturn = [UIColor brownColor];
            break;
        case 6 :
            colorToReturn = [UIColor cyanColor];
            break;
        case 7 :
            colorToReturn = [UIColor orangeColor];
            break;
        case 8 :
            colorToReturn = [UIColor magentaColor];
            break;
        case 9 :
            colorToReturn = [UIColor whiteColor];
            break;
        default :
            colorToReturn = [UIColor blackColor];

    }
    return(colorToReturn);
}

@end
KFDoom
  • 772
  • 1
  • 6
  • 19
  • If you can reproduce this crash easily. Step through the code with the debugger - tap the square and follow the code until it crashes. – Robert J. Clegg Aug 14 '15 at 04:48
  • Yes. It crashes at the if((specificSquare.xIndex...) line. I attempted to comment out the action within the if condition but to no avail. – KFDoom Aug 14 '15 at 04:50
  • Sorry, I neglected to mention that. – KFDoom Aug 14 '15 at 04:50
  • The issue is clear. Not all subviews of `self.view` are instances of your `FunViewSquare` class. Some are plain old `UIView` instances. – rmaddy Aug 14 '15 at 04:57
  • `for( MyType * obj in myArray )` does not filter the array to only loop on objects of `MyType`. You must do that yourself. – jscs Aug 14 '15 at 04:58

1 Answers1

2

The problem is that you're iterating through all the subviews in self.view and not all of those views are FunViewSquare views and don't all respond to xIndex. Hence the crash.

It seems you're assuming that the for loop will only pick out FunViewSquare objects in the subviews - this is simply not the case.

You need to do some introspection here - rewrite your code like this:

for(FunViewSquare *specificSquare in [self.view subviews]) {
 if ([specificSquare isKindOfClass:[FunViewSquare class]](
  if ((specificSquare.xIndex == xVIndex) && (specificSquare.yIndex == yIndex)){
           //specificSquare.backgroundColor = [ViewController randomColor];
  }
 }
}

This way you're checking to make sure that specificSquare really is a FunViewSquare object.

jscs
  • 63,694
  • 13
  • 151
  • 195
Robert J. Clegg
  • 7,231
  • 9
  • 47
  • 99
  • 1
    Strictly, it's incorrect to leave the cast of every `specificSquare` to `FunViewSquare`: you should consider changing the type of the loop's object to `UIView` and then reassigning after determining the type. – jscs Aug 14 '15 at 05:05