NSRangeException

时间:2011-06-16 20:39:23

标签: iphone objective-c xcode nsarray

我正在尝试使用两个按钮来循环显示一系列图像。我正在使用buttonPressed函数来识别左或右按钮的标记,并应更改显示的图像。问题是,当向右移动(递增数组)时,该函数可以正常工作,但如果我尝试向左移动(递减),程序将崩溃。我已经尝试更改变量初始化的值和用于循环数组的值,但似乎没有什么能解决它。非常感谢任何帮助。

·H

//  FirstViewController.h
//  TabTemplate
//
//  Created by Paul R Woidke on 6/1/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#include <stdlib.h>



@interface FirstViewController : UIViewController {
    UIImageView* hat;
    UIImageView* shirt;
    UIImageView* pants;
    UIImageView* shoes;

    NSArray *hatArray;
    NSArray *shirtArray;
    NSArray *pantsArray;
    NSArray *shoesArray;
}

@property (nonatomic, retain) IBOutlet UIImageView* hat;
@property (nonatomic, retain) IBOutlet UIImageView* shirt;
@property (nonatomic, retain) IBOutlet UIImageView* pants;
@property (nonatomic, retain) IBOutlet UIImageView* shoes;

@property (nonatomic, retain) IBOutlet NSArray* hatArray;
@property (nonatomic, retain) IBOutlet NSArray* shirtArray;
@property (nonatomic, retain) IBOutlet NSArray* pantsArray;
@property (nonatomic, retain) IBOutlet NSArray* shoesArray;

- (IBAction)buttonPressed:(id) sender;
- (IBAction)lockButtonPressed:(id) sender;
- (IBAction)weatherButtonPressed:(id) sender;
- (IBAction)randomizeButtonPressed:(id) sender;

@end

的.m

//  FirstViewController.m
//  TabTemplate
//
//  Created by Paul R Woidke on 6/1/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "FirstViewController.h"


@implementation FirstViewController

@synthesize hat;
@synthesize shirt;
@synthesize pants;
@synthesize shoes;

@synthesize hatArray;
@synthesize shirtArray;
@synthesize pantsArray;
@synthesize shoesArray;

NSInteger hatImage;
NSInteger shirtImage;
NSInteger pantsImage;
NSInteger shoesImage;

-(void) displayOutfit {
    UIImage *hatImg = [hatArray objectAtIndex:hatImage];
    [hat setImage:hatImg]; 
    UIImage *shirtImg = [shirtArray objectAtIndex:shirtImage];
    [shirt setImage:shirtImg]; 
    UIImage *pantsImg = [pantsArray objectAtIndex:pantsImage];
    [pants setImage:pantsImg]; 
    UIImage *shoesImg = [shoesArray objectAtIndex:shoesImage];
    [shoes setImage:shoesImg];  
}

- (IBAction)buttonPressed:(id) sender {

    NSInteger senderLabel = [sender tag];

    switch (senderLabel) {

//Going right
        case 2:

            NSLog(@"Hat number: %d", hatImage);
            NSLog(@"Hat Array count: %d", [hatArray count]);

            if (hatImage == [hatArray count])
                hatImage = 0;
            UIImage *hatImg2 = [hatArray objectAtIndex:hatImage];
            [hat setImage:hatImg2]; 
            hatImage++;
            break;

        case 4:
            if (shirtImage == [shirtArray count])
                shirtImage = 0;
            UIImage *shirtImg2 = [shirtArray objectAtIndex:shirtImage];
            [shirt setImage:shirtImg2]; 
            shirtImage++;
            break;

        case 6:
            if (pantsImage == [pantsArray count])
                pantsImage = 0;
            UIImage *pantsImg = [pantsArray objectAtIndex:pantsImage];
            [pants setImage:pantsImg]; 
            pantsImage++;
            break;

        case 8: 
            if (shoesImage == [shoesArray count])
                shoesImage = 0;
            UIImage *shoesImg2 = [shoesArray objectAtIndex:shoesImage];
            [shoes setImage:shoesImg2]; 
            shoesImage++;
            break;

//Going left
        case 1:
            if (hatImage == 0)
                hatImage = 3;
            UIImage *hatImg = [hatArray objectAtIndex:hatImage];
            [hat setImage:hatImg]; 
            hatImage--;
            break;

        case 3:
            if ((shirtImage) == 0)
                shirtImage = [shirtArray count];
            UIImage *shirtImg = [shirtArray objectAtIndex:shirtImage];
            [shirt setImage:shirtImg]; 
            shirtImage--;
            break;

        case 5:
            if ((pantsImage) == 0)
                pantsImage = [pantsArray count];
            UIImage *pantsImg2 = [pantsArray objectAtIndex:pantsImage];
            [pants setImage:pantsImg2]; 
            pantsImage--;
            break;

        case 7: 
            if ((shoesImage) == 0)
                shoesImage = [shoesArray count];
            UIImage *shoesImg = [shoesArray objectAtIndex:shoesImage];
            [shoes setImage:shoesImg]; 
            shoesImage--;
            break;

    }
}

- (IBAction)lockButtonPressed:(id) sender {
    NSLog(@"Lock Button Pressed");
}

- (IBAction)weatherButtonPressed:(id) sender {
    NSLog(@"Weather Button Pressed");
}

- (IBAction)randomizeButtonPressed:(id) sender {
    NSLog(@"Randomize Button Pressed");


    int randHat = rand() % [hatArray count];
    int randShirt = rand() % [shirtArray count];
    int randPants = rand() % [pantsArray count];
    int randShoes = rand() % [shoesArray count];
    NSLog(@"hat %d\nshirt %d\npants %d\nshoes %d", randHat, randShirt, randPants, randShoes);

    hatImage = randHat;
    shirtImage = randShirt;
    pantsImage = randPants;
    shoesImage = randShoes;

    [self displayOutfit];
}


/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {

    //Generate image arrays
    hatArray = [[NSArray arrayWithObjects: 
                    [UIImage imageNamed:@"h1.png"], 
                    [UIImage imageNamed:@"h2.png"], 
                    [UIImage imageNamed:@"h3.png"], 
                    nil] retain];

    shirtArray = [[NSArray arrayWithObjects: 
                   [UIImage imageNamed:@"s1.png"], 
                   [UIImage imageNamed:@"s2.png"],
                   [UIImage imageNamed:@"s3.png"], 
                   [UIImage imageNamed:@"s4.png"],
                   [UIImage imageNamed:@"s5.png"], 
                   [UIImage imageNamed:@"s6.png"],
                   nil] retain];

    pantsArray = [[NSArray arrayWithObjects: 
                   [UIImage imageNamed:@"p1.png"], 
                   [UIImage imageNamed:@"p2.png"],
                   [UIImage imageNamed:@"p3.png"],
                   [UIImage imageNamed:@"p4.png"],
                   nil] retain];

    shoesArray = [[NSArray arrayWithObjects: 
                   [UIImage imageNamed:@"ss1.png"], 
                   [UIImage imageNamed:@"ss2.png"],
                   [UIImage imageNamed:@"ss3.png"],
                   nil] retain];

    hatImage = 0;
    shirtImage = 0;
    pantsImage = 0;
    shoesImage = 0;

    UIImage *hatImg = [hatArray objectAtIndex:hatImage];
    [hat setImage:hatImg]; 
    UIImage *shirtImg = [shirtArray objectAtIndex:shirtImage];
    [shirt setImage:shirtImg]; 
    UIImage *pantsImg = [pantsArray objectAtIndex:pantsImage];
    [pants setImage:pantsImg]; 
    UIImage *shoesImg = [shoesArray objectAtIndex:shoesImage];
    [shoes setImage:shoesImg]; 

    [super viewDidLoad];
}


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.hat = nil;
    self.shirt = nil;
    self.pants = nil;
    self.shoes = nil;
    self.hatArray = nil;
    self.shirtArray = nil;
    self.pantsArray = nil;
    self.shoesArray = nil;
}


- (void)dealloc {
    [hat release];
    [shirt release];
    [pants release];
    [shoes release];
    [hatArray release];
    [shirtArray release];
    [pantsArray release];
    [shoesArray release];
    [super dealloc];
}

@end

控制台输出(显示数组计数和当前图像的值):

[Session started at 2011-06-16 16:30:50 -0400.]
2011-06-16 16:31:03.192 TabTemplate[2478:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00db3be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00f085c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00da980c -[__NSArrayI objectAtIndex:] + 236
    3   TabTemplate                         0x000026c8 -[FirstViewController buttonPressed:] + 569
    4   UIKit                               0x002bca6e -[UIApplication sendAction:to:from:forEvent:] + 119
    5   UIKit                               0x0034b1b5 -[UIControl sendAction:to:forEvent:] + 67
    6   UIKit                               0x0034d647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
    7   UIKit                               0x0034c1f4 -[UIControl touchesEnded:withEvent:] + 458
    8   UIKit                               0x002e10d1 -[UIWindow _sendTouchesForEvent:] + 567
    9   UIKit                               0x002c237a -[UIApplication sendEvent:] + 447
    10  UIKit                               0x002c7732 _UIApplicationHandleEvent + 7576
    11  GraphicsServices                    0x016e9a36 PurpleEventCallback + 1550
    12  CoreFoundation                      0x00d95064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    13  CoreFoundation                      0x00cf56f7 __CFRunLoopDoSource1 + 215
    14  CoreFoundation                      0x00cf2983 __CFRunLoopRun + 979
    15  CoreFoundation                      0x00cf2240 CFRunLoopRunSpecific + 208
    16  CoreFoundation                      0x00cf2161 CFRunLoopRunInMode + 97
    17  GraphicsServices                    0x016e8268 GSEventRunModal + 217
    18  GraphicsServices                    0x016e832d GSEventRun + 115
    19  UIKit                               0x002cb42e UIApplicationMain + 1160
    20  TabTemplate                         0x00002012 main + 84
    21  TabTemplate                         0x00001f92 start + 54
)
terminate called after throwing an instance of 'NSException'

[Session started at 2011-06-16 16:31:13 -0400.]
2011-06-16 16:31:15.966 TabTemplate[2481:207] Hat number: 0
2011-06-16 16:31:15.968 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:16.390 TabTemplate[2481:207] Hat number: 1
2011-06-16 16:31:16.391 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:16.790 TabTemplate[2481:207] Hat number: 2
2011-06-16 16:31:16.791 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:17.446 TabTemplate[2481:207] Hat number: 3
2011-06-16 16:31:17.447 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:17.902 TabTemplate[2481:207] Hat number: 1
2011-06-16 16:31:17.903 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:18.199 TabTemplate[2481:207] Hat number: 2
2011-06-16 16:31:18.199 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:18.526 TabTemplate[2481:207] Hat number: 3
2011-06-16 16:31:18.527 TabTemplate[2481:207] Hat Array count: 3
2011-06-16 16:31:20.503 TabTemplate[2481:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00db3be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00f085c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00da980c -[__NSArrayI objectAtIndex:] + 236
    3   TabTemplate                         0x000026c8 -[FirstViewController buttonPressed:] + 569
    4   UIKit                               0x002bca6e -[UIApplication sendAction:to:from:forEvent:] + 119
    5   UIKit                               0x0034b1b5 -[UIControl sendAction:to:forEvent:] + 67
    6   UIKit                               0x0034d647 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
    7   UIKit                               0x0034c1f4 -[UIControl touchesEnded:withEvent:] + 458
    8   UIKit                               0x002e10d1 -[UIWindow _sendTouchesForEvent:] + 567
    9   UIKit                               0x002c237a -[UIApplication sendEvent:] + 447
    10  UIKit                               0x002c7732 _UIApplicationHandleEvent + 7576
    11  GraphicsServices                    0x016e9a36 PurpleEventCallback + 1550
    12  CoreFoundation                      0x00d95064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    13  CoreFoundation                      0x00cf56f7 __CFRunLoopDoSource1 + 215
    14  CoreFoundation                      0x00cf2983 __CFRunLoopRun + 979
    15  CoreFoundation                      0x00cf2240 CFRunLoopRunSpecific + 208
    16  CoreFoundation                      0x00cf2161 CFRunLoopRunInMode + 97
    17  GraphicsServices                    0x016e8268 GSEventRunModal + 217
    18  GraphicsServices                    0x016e832d GSEventRun + 115
    19  UIKit                               0x002cb42e UIApplicationMain + 1160
    20  TabTemplate                         0x00002012 main + 84
    21  TabTemplate                         0x00001f92 start + 54
)
terminate called after throwing an instance of 'NSException'

2 个答案:

答案 0 :(得分:2)

在“向左”的情况下,您将数组索引设置为超出范围。例如:

if ((shirtImage) == 0)
    shirtImage = [shirtArray count];

数组中的最后一项具有索引[arrayObj count] - 1

事实上,你将shirtImage的值设置在1..arrayLength范围内的任何位置,它应该在0..arrayLength-1范围内。我建议你先增加/减少你的索引,然后检查它的边界,然后索引到数组。例如:

case 2:
    // increment the index
    hatImage++; 

    // wrap around if you've gone beyond the bounds of the array
    if (hatImage == [hatArray count])
        hatImage = 0;

    // Index into the array
    [hat setImage:[hatArray objectAtIndex:hatImage]];

答案 1 :(得分:0)

NSRangeException - 这意味着你已经超出了数组的范围。

旁白:您将这些声明为IBOutlet属性。你把它们挂钩到什么地方?

@property (nonatomic, retain) IBOutlet NSArray* hatArray;
@property (nonatomic, retain) IBOutlet NSArray* shirtArray;
@property (nonatomic, retain) IBOutlet NSArray* pantsArray;
@property (nonatomic, retain) IBOutlet NSArray* shoesArray;