App crashing with alert view

0

I'm new to Objective C and I have a question. I created an alert view and got a text field inside of it so when the user tries to put in a name he/she can have the label named what he/she entered for the file name. When the user clicks the button stating "new" an alert appears with a text box prompting the user to enter a name for the file. Once they have done that, the button stating "new" will be hidden and a label stating the text they entered will unhide itself. If they feel they don't want the file anymore they have the option to delete it. When they click the delete button an alert comes up asking them if they would like to delete the file with two buttons: Yes and No, but if they click Yes it crashes the application. Please help.

Here is my header file:

#import <UIKit/UIKit.h>

NSString *File0Name;
NSString *File1Name;
NSString *File2Name;
NSString *File3Name;

int file;
int delet;

@interface Load : UIViewController <UIAlertViewDelegate>
{
    IBOutlet UIButton *File1;
    IBOutlet UIButton *File2;
    IBOutlet UIButton *File3;

    IBOutlet UIButton *DeleteFile1;
    IBOutlet UIButton *DeleteFile2;
    IBOutlet UIButton *DeleteFile3;

    IBOutlet UILabel *File1Label;
    IBOutlet UILabel *File2Label;
    IBOutlet UILabel *File3Label;

}

-(IBAction)File1:(id)sender;
-(IBAction)File2:(id)sender;
-(IBAction)File3:(id)sender;

-(IBAction)DeleteFile1:(id)sender;
-(IBAction)DeleteFile2:(id)sender;
-(IBAction)DeleteFile3:(id)sender;

@end

Here is my implementation file:

-(IBAction)DeleteFile1:(id)sender{
    NSString *delete1 = [NSString stringWithFormat:@"Are you sure you would like to   delete %@", File1Name];
   UIAlertView *Delete1 = [[UIAlertView alloc] initWithTitle:@"Delete File"  message:delete1 delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No", nil];
  [Delete1 show];

  delet = 1; //This is sortive like a tag so when I specify which button was clicked I can also specify which alert it is for

}

-(IBAction)DeleteFile2:(id)sender{
    NSString *delete2 = [NSString stringWithFormat:@"Are you sure you would like to    delete %@", File2Name];
    UIAlertView *Delete2 = [[UIAlertView alloc] initWithTitle:@"Delete File" message:delete2 delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No", nil];
    [Delete2 show];

    delet = 2; //This is sortive like a tag so when I specify which button was clicked I can also specify which alert it is for

}

-(IBAction)DeleteFile3:(id)sender{
    NSString *delete3 = [NSString stringWithFormat:@"Are you sure you would like to delete %@", File3Name];
    UIAlertView *Delete3 = [[UIAlertView alloc] initWithTitle:@"Delete File" message:delete3 delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No", nil];
    [Delete3 show];

    delet = 3; //This is like a tag so when I specify which button was clicked I can also specify which alert it is for
}

-(IBAction)File1:(id)sender{
UIAlertView *Alert1 = [[UIAlertView alloc] initWithTitle:@"Name this file!" message:@"Enter a name for this new file." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:@"Cancel", nil];
Alert1.alertViewStyle = UIAlertViewStylePlainTextInput;
[Alert1 show];

file = 1; //This is also like a tag so when I specify which button was clicked I can   also specify which alert it is for

}

-(IBAction)File2:(id)sender{
UIAlertView *Alert2 = [[UIAlertView alloc] initWithTitle:@"Name this file!" message:@"Enter a name for this new file." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:@"Cancel", nil];
Alert2.alertViewStyle = UIAlertViewStylePlainTextInput;
[Alert2 show];

    file = 2; //This is also like a tag so when I specify which button was clicked I can also specify which alert it is for
}

-(IBAction)File3:(id)sender{
    UIAlertView *Alert3 = [[UIAlertView alloc] initWithTitle:@"Name this file!"   message:@"Enter a name for this new file." delegate:self cancelButtonTitle:@"Ok"  otherButtonTitles:@"Cancel", nil];
    Alert3.alertViewStyle = UIAlertViewStylePlainTextInput;
   [Alert3 show];

   file = 3; //This is also like a tag so when I specify which button was clicked I can also specify which alert it is for
  }

 -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:    (NSInteger)buttonIndex{

    if ((buttonIndex == 0) && (file == 1)) {
        File1Name = [[alertView textFieldAtIndex:0] text];
        File1Label.text = File1Name;
        File1.hidden = YES;
        File1Label.hidden = NO;
        DeleteFile1.hidden = NO;
        NSLog(@"%@", File1Label.text);

    }

    if ((buttonIndex == 0) && (file == 2)) {
        File2Name = [[alertView textFieldAtIndex:0] text];
        File2Label.text = File2Name;
        File2.hidden = YES;
        File2Label.hidden = NO;
        DeleteFile2.hidden = NO;
        NSLog(@"%@", File2Label.text);

    }

    if ((buttonIndex == 0) && (file == 3)) {
        File3Name = [[alertView textFieldAtIndex:0] text];
        File3Label.text = File3Name;
        File3.hidden = YES;
        File3Label.hidden = NO;
        DeleteFile3.hidden = NO;
        NSLog(@"%@", File3Label.text);
    }

    if ((buttonIndex == 0) && (file == 1)) {
        File1Name = [[alertView textFieldAtIndex:0] text];
        File1Label.text = File1Name;
        File1.hidden = YES;
        File1Label.hidden = NO;
        DeleteFile1.hidden = NO;
        NSLog(@"%i", File1.hidden);
        NSLog(@"%i", File1Label.hidden);
    }

    if ((buttonIndex == 0) && (delet == 1)) {
        File1Label.hidden = YES;
        File1Label.text = @"Label";
        File1.hidden = NO;
        DeleteFile1.hidden = YES;
    }

   if ((buttonIndex == 0) && (delet == 2)) {
       File2Label.hidden = YES;
       File2Label.text = @"Label";
       File2.hidden = NO;
       DeleteFile2.hidden = YES;
   }

   if ((buttonIndex == 0) && (delet == 3)) {
      File3Label.hidden = YES;
      File3Label.text = @"Label";
      File3.hidden = NO;
      DeleteFile3.hidden = YES;
   }

}

- (void)viewDidLoad
{
    DeleteFile1.hidden = YES;
    DeleteFile2.hidden = YES;
    DeleteFile3.hidden = YES;

    File1.hidden = NO;
    File1Label.hidden = YES;

    File2.hidden = NO;
    File2Label.hidden = YES;

   File3.hidden = NO;
   File3Label.hidden = YES;
  [super viewDidLoad];
  // Do any additional setup after loading the view.
}

@end

Just in case you're wondering I took out the other methods like "did receive memory warning" here so this wouldn't be so long, but in my real .m file I have them.

If this helps, here is what has been displayed in the debugger console:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:       'textFieldIndex (0) is outside of the bounds of the array of text fields'
*** First throw call stack:
(
0   CoreFoundation                      0x0185b1e4 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x015da8e5 objc_exception_throw + 44
2   CoreFoundation                      0x0185afbb +[NSException raise:format:] + 139
3   UIKit                               0x007af61d -[UIAlertView textFieldAtIndex:] + 97
4   Balloon Assault                     0x00003700 -[Load alertView:clickedButtonAtIndex:] + 144
5   UIKit                               0x007a9733 -[UIAlertView modalItem:tappedButtonAtIndex:] + 67
6   UIKit                               0x0087bac5 -[_UIModalItemsCoordinator _notifyDelegateModalItem:tappedButtonAtIndex:] + 180
7   UIKit                               0x003b01c8 -[_UIModalItemAlertContentView tableView:didSelectRowAtIndexPath:] + 1035
8   UIKit                               0x003849a1 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1513
9   UIKit                               0x00384b14 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 279
10  UIKit                               0x0038910e __38-[UITableView touchesEnded:withEvent:]_block_invoke + 43
11  UIKit                               0x002b80aa ___afterCACommitHandler_block_invoke + 15
12  UIKit                               0x002b8055 _applyBlockToCFArrayCopiedToStack + 403
13  UIKit                               0x002b7e76 _afterCACommitHandler + 532
14  CoreFoundation                      0x0182336e      __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
15  CoreFoundation                      0x018232bf __CFRunLoopDoObservers + 399
16  CoreFoundation                      0x01801254 __CFRunLoopRun + 1076
17  CoreFoundation                      0x018009d3 CFRunLoopRunSpecific + 467
18  CoreFoundation                      0x018007eb CFRunLoopRunInMode + 123
19  GraphicsServices                    0x0218e5ee GSEventRunModal + 192
20  GraphicsServices                    0x0218e42b GSEventRun + 104
21  UIKit                               0x0029af9b UIApplicationMain + 1225
22  Balloon Assault                     0x0000488d main + 141
23  libdyld.dylib                       0x0268e701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
objective-c
crash
asked on Stack Overflow Jun 1, 2014 by MarsTech • edited Jun 2, 2014 by matt

1 Answer

1

You are crashing because you are saying, for example,

File1Name = [[alertView textFieldAtIndex:0] text];

But your alert view has no text fields. Look at how you create the alert view. You are saying, for example:

[[UIAlertView alloc] initWithTitle:@"Delete File"  message:delete1 delegate:self cancelButtonTitle:@"Yes" otherButtonTitles:@"No", nil];

There is no text field in that alert view, and you are not putting one there. For some of your alert views, you are setting the alertViewStyle to UIAlertViewStylePlainTextInput which does give you one text field. But for others you are not. So when your delegate code encounters an alert view that doesn't have one, you crash.

Clearly your technique for deciding in your delegate method which of your alert views you are responding to is not working. And this is not surprising, since you are not setting both file and delet in every case. But in any case it's a poor idea, since the alert view is one thing and instance variables located in your Load object are another. This was a bad way of making this distinction, right from the start.

Your comment about this technique says "this is like a tag". But it's not like a tag. A tag would belong to the alert view (or something within it).

The way to distinguish which alert view this is, is to look at something about the alert view itself. For example, ask for its alertViewStyle! This will tell you whether it has any text fields or not.

answered on Stack Overflow Jun 1, 2014 by matt • edited Jun 1, 2014 by matt

User contributions licensed under CC BY-SA 3.0