6

I am getting the following error message which I cannot understand why its happening because I am not using any UIImageView. Sometimes I get the same error but its a CALayer?!?

Its worth also mentioning that I have 2 nibs and 2 controllers and a base controller where this code resides.

EDIT:

This is the structure of my project

MainViewController & its nib - HomeViewController in nib

MainViewController-Landscape & its nib - HomeViewController-Landscape in nib

HomeViewControllerBase - no nib - Base class where all outlets and item configuration code exists. - Outlets are used by both child classes below. - Outlets are linked to controls in each of the main nibs.

HomeViewController - Inherits from HomeViewControllerBase

HomeViewController-Landscape - Inherits from HomeViewControllerBase

So whats happening is that the child class is trying to dealloc its base class (which has all the outlets in it). I have designed it this way to avoid duplication of code in the different orientation viewcontrollers.

@implementation MainViewController
- (void)orientationChanged:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

    if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
    {
        [self presentModalViewController:self.landscapeViewController
                                animated:YES];

        isShowingLandscapeView = YES;
    }
    else if (UIDeviceOrientationIsPortrait(deviceOrientation) && isShowingLandscapeView)
    {
        [self dismissModalViewControllerAnimated:YES];
        isShowingLandscapeView = NO;
    }
}

- (id)init
{
    self = [super initWithNibName:@"MainViewController" bundle:nil];

    if (self)
    {
        isShowingLandscapeView = NO;
        self.landscapeViewController = [[[MainViewController_Landscape alloc]
                                            initWithNibName:@"MainViewController-Landscape" bundle:nil] autorelease];

        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(orientationChanged:)
                                                     name:UIDeviceOrientationDidChangeNotification
                                                   object:nil];
    }

    return self;
}
@end

@implementation HomeViewControllerBase

    - (void)bestSellItemTapped:(id)sender
    {
        NSLog(@"best sell item tapped");
    }

    - (void)configureBestSellItems
    {
        [self startRetrievingRegions];

        // load all the images from our bundle and add them to the scroll view
        //  NSUInteger i;
        for (int i = 0; i <= 150; i++)
        {

            UILabel *itemTitle = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 50)];
            itemTitle.text = @"Majorca";

            UILabel *itemPrice = [[UILabel alloc]initWithFrame:CGRectMake(0, 50, 100, 50)];
            itemPrice.text = @"£249";

            NSString *imageName = @"tempImage.jpg";
            UIImage *image = [UIImage imageNamed:imageName];


            UIButton *mainButton = [[[UIButton alloc]init] autorelease];

            [mainButton addTarget:self action:@selector(bestSellItemTapped:) forControlEvents:UIControlEventTouchUpInside];
            [mainButton setBackgroundImage:image forState:UIControlStateNormal];



            // setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
            CGRect rect = mainButton.frame;
            rect.size.height = kScrollObjHeight;
            rect.size.width = kScrollObjWidth;

            mainButton.frame = rect;
            mainButton.tag = i;


            [mainButton addSubview:itemTitle]; [itemTitle release];
            [mainButton addSubview:itemPrice]; [itemPrice release];




            [self.bestSellScrollView addSubview:mainButton];


        }

        [self layoutScrollImages];  // now place the photos in serial layout within the scrollview
    }


    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self configureBestSellItems];
    }

    - (void)layoutScrollImages
    {
        UIButton *view = nil;
        NSArray *subviews = [self.bestSellScrollView subviews];

        // reposition all image subviews in a horizontal serial fashion
        CGFloat curXLoc = 0;
        for (view in subviews)
        {
            if ([view isKindOfClass:[UIButton class]] && view.tag > 0)
            {
                CGRect frame = view.frame;
                frame.origin = CGPointMake(curXLoc, 0);
                view.frame = frame;

                curXLoc += (kScrollObjWidth + kScrollObjPadding);
            }
        }

        // set the content size so it can be scrollable
        [self.bestSellScrollView setContentSize:CGSizeMake((150 * kScrollObjWidth), 
                                                           [self.bestSellScrollView bounds].size.height)];
    }

@end

@interface HomeViewController : HomeViewControllerBase
@end

@interface HomeViewController_Landscape : HomeViewControllerBase
@end

@implementation HomeViewController

- (void)dealloc
{
    [super dealloc]; //When I remove this it works
}

@end

@implementation HomeViewController_Landscape

- (void)dealloc
{
   [super dealloc]; //When I remove this it works
}

@end

-[UIImageView bestSellItemTapped:]: unrecognized selector sent to instance 0x681c2b0 2011-04-12 15:45:26.665 [21532:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImageView bestSellItemTapped:]: unrecognized selector sent to instance 0x681c2b0'
*** Call stack at first throw: (    0   CoreFoundation                      0x00dc85a9 __exceptionPreprocess + 185  1   libobjc.A.dylib                   0x00f1c313 objc_exception_throw + 44  2   CoreFoundation                    0x00dca0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187  3   CoreFoundation                      0x00d39966 ___forwarding___ + 966   4   CoreFoundation                      0x00d39522 _CF_forwarding_prep_0 + 50   5   UIKit                             0x0001a4fd -[UIApplication sendAction:to:from:forEvent:] + 119    6 UIKit                               0x000aa799 -[UIControl sendAction:to:forEvent:] + 67  7   UIKit                               0x000acc2b -[UIControl(Internal)
_sendActionsForEvents:withEvent:] + 527     8   UIKit                         0x000ab7d8 -[UIControl touchesEnded:withEvent:] + 458     9   UIKit                               0x002ad4de
_UIGestureRecognizerSortAndSendDelayedTouches
+ 3609  10  UIKit                               0x002adc53
_UIGestureRecognizerUpdateObserver + 927    11  CoreFoundation                0x00da989b
__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
+ 27    12  CoreFoundation                      0x00d3e6e7 __CFRunLoopDoObservers + 295     13  CoreFoundation                0x00d071d7 __CFRunLoopRun + 1575  14  CoreFoundation                      0x00d06840 CFRunLoopRunSpecific + 208   15  CoreFoundation                    0x00d06761 CFRunLoopRunInMode + 97    16 GraphicsServices                    0x010001c4 GSEventRunModal + 217     17  GraphicsServices                    0x01000289 GSEventRun + 115     18  UIKit 0x00028c93 UIApplicationMain + 1160   19                      0x000027a9 main + 121   20 
                      0x00002725 start + 53 ) terminate called after throwing an instance of 'NSException'
Neeku
  • 3,646
  • 8
  • 33
  • 43
TheLearner
  • 19,387
  • 35
  • 95
  • 163
  • 1
    One thing I'm noticing is that you make the contentSize of the scrollview 150 times something while you're creating 151 buttons. – onnoweb Apr 12 '11 at 15:18
  • Possible duplicate of [How can I debug 'unrecognized selector sent to instance' error](https://stackoverflow.com/questions/25853947/how-can-i-debug-unrecognized-selector-sent-to-instance-error) – Cœur Jul 08 '19 at 05:50

3 Answers3

2

Is the whatever ViewController this code is from still alive when the button is tapped? An error like this (unrelated object - UIImageView in this case) usually means you have a pointer to some area of the memory that has been released and reused for something else (UIImageView in this case).

Add an NSLog() printout to the -dealloc method of the view controller and make sure it's not fired before you tap the button.

Actually, add one more NSLog to the beginning of configureBestSellItems - NSLog(@"I am %x", self); (yes, %x, not %@). This will print out the address of your view controller - compare it with the address of the crashing object (as in "unrecognized selector sent to instance 0x681c2b0" - see if it prints "I am 0x681c2b0" initially)

Kanan Vora
  • 2,124
  • 1
  • 16
  • 26
SVD
  • 4,743
  • 2
  • 26
  • 38
  • @SVD - I removed the [super dealloc] from the child controllers and that seemed to work however I am not sure if the base controller is ever going to be released now!? – TheLearner Apr 12 '11 at 16:38
  • 1
    Removing `[super dealloc]` is the wrong thing to do. You clearly have a problem with whatever controller is `self` being dealloc'ed unexpectedly but by removing `[super dealloc]` you are obscuring the problem, not solving it. You should post more code related to how your main view controller is instantiated and presented. That should be where the issue is. – XJones Apr 12 '11 at 16:41
  • @TheLearner removing [super dealloc] confirms you have an unexpected release somewhere, but certainly not a solution. – SVD Apr 12 '11 at 16:52
  • @SVD I am in the iPhone/iPad chat room if you have any other Q's - appreciate your help – TheLearner Apr 12 '11 at 18:54
  • OK, so does the problem happen when you switch to landscape? Or when you switch to landscape and back? Do you share the bestSellScrollView between your landscape and portrait views? You may want to add breakpoints (or NSLog()s) to dealloc methods of both views and see if they are released at an unexpected moment. – SVD Apr 13 '11 at 15:27
  • when the main: method executes, dealloc is called on homeviewcontroller and in turn homeviewcontrollerbase which i cannot understand. then when you switch from portrait to landscape dealloc is called on homeviewcontroller-landscape and then homeviewcontrollerbase - so dealloc is being called just before the view is shown - I don't understand this. – TheLearner Apr 14 '11 at 13:27
  • There are 2 best sell scrollviews - one on each orientation nib which are linked to a single outlet – TheLearner Apr 14 '11 at 13:53
  • Does the self.landscapeViewController retain the view controller? – SVD Apr 14 '11 at 15:46
  • Still have the same problem even with my new design - the homeviewcontrollers are calling dealloc - I cannot determine why! Any help would be greatly appreciated – TheLearner Apr 19 '11 at 15:26
1

If you are working with InterfaceBuilder and did some connecting / linking GUI-elements to IBActions / methods in the controllers header file right-click or "cntrl+click" that GUI-element that causes the error for being connected / linked to still existing methods only.

See `unrecognized selector sent to instance <OBJ_ADR>`after sending `dismissViewControllerAnimated:completion` to a UIViewController

Community
  • 1
  • 1
noone
  • 155
  • 1
  • 2
  • 10
0

When you alloced your UIButton , you flagged that as autorelease , this could be the reason of crash because there are possibilites of claiming mainButton by the system ,

UIButton *mainButton = [[[UIButton alloc]init] autorelease];

Check with removing autorelease and if it work make your UIButton as class variable or use UIButton's buttonWithtype to get the button from system .

Jhaliya - Praveen Sharma
  • 31,697
  • 9
  • 72
  • 76
  • Removed the autorelease and get the same error except from CALayer – TheLearner Apr 12 '11 at 15:24
  • This is not the problem. You need to release `mainButton`. Your autorelease was correct. If you remove it, then you need to explicitly release `mainButton` after you add it to its superview. – XJones Apr 12 '11 at 16:33