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
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.
User contributions licensed under CC BY-SA 3.0