Hey, I am pretty surprised at the fact that this code is not working right now:
Code:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIAlertView *termsconditions = [[UIAlertView alloc]
initWithTitle:@"Terms & Conditions"
message:[NSString stringWithFormat:@"We advise all users to review these Terms and Conditions to enjoy all of our features and benefits. Failure to view and accept said terms revokes our responsibility for your experience using this application'." , nil]
delegate:self cancelButtonTitle:@"I Agree"
otherButtonTitles: @"Submitting Conditions" , @"Commissions Conditions" , nil];
[termsconditions show];
[termsconditions release];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)alert:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
switch(buttonIndex) {
case 0:
break;
case 1: {
SubmittingTermsViewController *submitterms = [[SubmittingTermsViewController alloc] initWithNibName:nil bundle:nil];
[tabBarController presentModalViewController:submitterms animated:YES];
}
break;
case 2: {
ConditionsViewController *commissionsterms = [[ConditionsViewController alloc] initWithNibName:nil bundle:nil];
[tabBarController presentModalViewController:commissionsterms animated:YES];
break;
}
default:
break;
}
}
}
The problem, although the alert appears at launch fine, all 3 cases (the choices) only dismiss the message, instead of performing the requested action (calling new views in this example, although I have 3 total locations for alerts).
*I also want this code to only appear until case 0 has been selected once. (So that once someone chooses "I Agree," they won't have to click that everytime).
I tested the code sample you gave except I just put NSLogs for each case in the switch statement. This delegate function never even gets entered into.
You're currently using: - (void)alert:... clickedButtonAtIndex: ....
I double checked the API Reference, the method is actually: - (void)alertView:... clickedButtonAtIndex: ....
I made this change, and voila, it started working. Hope this helps!
BTW, there was an extra close curly bracket '}' at the end of the code you pasted, not sure if that was just a pasting error or not but thought I'd mention it.
*I also want this code to only appear until case 0 has been selected once. (So that once someone chooses "I Agree," they won't have to click that everytime).
For this issue, I'd look into NSUserDefaults. There's several threads on the forum about it, but basically it allows you to save values/settings and then fetch them again later (even when app is closed and reopened).
A quick example would be:
Code:
//Get a reference to the standardUserDefaults
NSUserDefaults *defaultPrefs= [NSUserDefaults standardUserDefaults];
//Save a key/value
[defaultPrefs setBool:YES forKey:@"acceptedTermsConditions"];
//Retrieve the value for specific key
BOOL myBool = [defaultPrefs boolForKey:@"acceptedTermsConditions"]
If you try to retrieve a BOOL value for a key that doesn't exist, the boolForKey method will return NO. This should work perfectly for your needs. Only show the alertview if the value is NO. Set the value to YES when they click I agree.
I tested the code sample you gave except I just put NSLogs for each case in the switch statement. This delegate function never even gets entered into.
You're currently using: - (void)alert:... clickedButtonAtIndex: ....
I double checked the API Reference, the method is actually: - (void)alertView:... clickedButtonAtIndex: ....
I made this change, and voila, it started working. Hope this helps!
BTW, there was an extra close curly bracket '}' at the end of the code you pasted, not sure if that was just a pasting error or not but thought I'd mention it.
- kalx
thanks for the mention of the extra curly (that was a copy and paste misque), but the change to alertView doesn't change the response at all, unfortunately. The three buttons continue to appear, but all of them dismiss the message instead of calling the modalview (like intended).
Observations/Questions
1. Have you dropped in a log statement to verify that the clickedButtonAtIndex: is being called? If no, do it and see what happens. Figure out if the problem is with the alert view or with the case statement.
2. Why is your message a stringWithFormat, when you aren't doing any formatting? And you have an extra single quote typo at the end of the string.
3. Both case 1 and 2 are leaks. Release those view controllers.
Regardless of which button is pressed, the UIAlertView will be automatically dismissed after the "alertView:clickedButtonAtIndex:" is invoked - that's just how the method works.
However, you should still see the code for each of your switch cases getting executed. Try putting an NSLog(@"Case #<Number here>") in each switch case, then run your app. Check the Debugger Console as you click each button, if you see the NSLog statement show up then at least you know that your code is successfully going to where it needs to go, and your problem gets limited to the ViewController and presentModalViewController:animated: code lines.
- kalx
EDIT: Looks like BrianSlick beat me by a few minutes!
Are you conforming to the <UIAlertViewDelegate> protocol in your header file?
im not sure what you mean by conforming to it? this may be something simple im missing, but ive been learning from tutorials, trial and error, and experience, but havent seen any suggestions for adding more to the header than the IBAction that would initiate it (in other examples).
im not sure what you mean by conforming to it? this may be something simple im missing, but ive been learning from tutorials, trial and error, and experience, but havent seen any suggestions for adding more to the header than the IBAction that would initiate it (in other examples).
Regardless of which button is pressed, the UIAlertView will be automatically dismissed after the "alertView:clickedButtonAtIndex:" is invoked - that's just how the method works.
However, you should still see the code for each of your switch cases getting executed. Try putting an NSLog(@"Case #<Number here>") in each switch case, then run your app. Check the Debugger Console as you click each button, if you see the NSLog statement show up then at least you know that your code is successfully going to where it needs to go, and your problem gets limited to the ViewController and presentModalViewController:animated: code lines.
- kalx
EDIT: Looks like BrianSlick beat me by a few minutes!
Actually, I know that UIAlertView's can have actions invoked. I think your suggestion for the NSLog #s in should work, but where would I specify each case's associated button. Thanks, I know that I am having trouble understanding some of the basics of this method controller, but I do appreciate the help you 2 are helping me out.
Actually, I know that UIAlertView's can have actions invoked. I think your suggestion for the NSLog #s in should work, but where would I specify each case's associated button. Thanks, I know that I am having trouble understanding some of the basics of this method controller, but I do appreciate the help you 2 are helping me out.
The problem here can either be the alertView not working properly, or the code in your case statements where you create a viewcontroller instance, and use the presentModalViewController, or possibly a mix of both.
then you can run your app in the simulator, and see if the NSLog statements show up in the Debugger Console. This will verify that the UIAlertView, and the buttons are working fine. Once you verify this, you know that there's no problem with your alertview - you just tested its functionality and the NSLogs showed you that it's executing properly and going where you expect it to go in your code. Thus, your problem ends up boiling down to the code inside each case statement (viewController, presentModalViewController).
After adding the NSLogs in each case, I don't receive any major difference. I did have one deal of progress: a activity indicator later called to appear (.hidden = FALSE) now appears and starts animating, which didn't happen before. This code is in the same action ["login"] and is the result of the agreement [alert button = "I Agree"] . Currently, my code looks like the following (now including some more, and you may notice I now am employing this action after a button ["Log In"] is chosen, opposed to the application launch).
Code:
- (IBAction)login:(id)sender
{
UIAlertView *termsconditions = [[UIAlertView alloc]
initWithTitle:@"Terms & Conditions!" message:@"Please review the following terms to ensure the best experience with the application. Failure to accept these terms revokes our responsibility for the quality of your experience with us."
delegate:self
cancelButtonTitle:@"I Agree"
otherButtonTitles:nil];
[termsconditions addButtonWithTitle:@"Submit Terms"];
[termsconditions addButtonWithTitle:@"Commission Terms"];
[termsconditions addButtonWithTitle:@"Privacy Terms"];
[termsconditions show];
[termsconditions release];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"Made it to the delegate method! The alert view works!");
switch(buttonIndex)
{
case 0:
{
NSLog(@"The first button was pressed");
break;
}
case 1:
{
NSLog(@"The second button was pressed");
SubmittingTermsViewController *submitterms = [[SubmittingTermsViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:submitterms animated:YES];
[submitterms release], submitterms = nil;
break;
}
case 2:
{
NSLog(@"The third button was pressed");
ConditionsViewController *commissionsterms = [[ConditionsViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:commissionsterms animated:YES];
[commissionsterms release], commissionsterms = nil;
break;
}
case 3:
{
NSLog(@"The fourth button was pressed");
SitewidePoliciesViewController *privacyterms = [[SitewidePoliciesViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:privacyterms animated:YES];
[privacyterms release], privacyterms = nil;
break;
}
default:
{
NSLog(@"Something went wrong");
break;
}
}
NSLog(@"Now we're leaving the delegate method. Did anything happen?");
// TODO: spawn a login thread
activityindicatorlogin.hidden = FALSE;
[activityindicatorlogin startAnimating];
buttonlogin.enabled = FALSE;
buttoninfo.enabled = FALSE;
buttonterms.enabled = FALSE;
buttonnewuser.enabled = FALSE;
buttonfullsite.enabled = FALSE;
buttonemailus.enabled = FALSE;
fieldpasswordlogin.enabled = FALSE;
fieldusernamelogin.enabled = FALSE;
}
Thanks in advance, both of you. I am getting tired and am hoping to finally get this working sooner than later [then apply similar actions elsewhere within the application], and I truly appreciate both of your quick responses and provided help.
Are you looking in the console view? In the Xcode menu (top of screen), click Run > Console, or use the shortcut Command+Shift+R, this'll open up the Debugger Console. The NSLog statements will show in this console as your program runs.
So, you run Build and Go, make sure you have the console open and visible, and then try the alertview in your app. You should (hopefully) see the NSLog messages appear in the console, and it helps you see what your code is doing. If you see the proper NSLog show up when you click each button, then your UIAlertView has no problems and is working fine, and you should check you other code that's within each case statement.
Are you looking in the console view? In the Xcode menu (top of screen), click Run > Console, or use the shortcut Command+Shift+R, this'll open up the Debugger Console. The NSLog statements will show in this console as your program runs.
So, you run Build and Go, make sure you have the console open and visible, and then try the alertview in your app. You should (hopefully) see the NSLog messages appear in the console, and it helps you see what your code is doing. If you see the proper NSLog show up when you click each button, then your UIAlertView has no problems and is working fine, and you should check you other code that's within each case statement.
- kalx
thankyou, ive never used NSLogs before and didnt fully understand there value until that. after checking IB, I realize that the last thing to complete the code was switching *loginview to self. I appreciate the help (and am slightly embarassed at how part of the problem was caused by my misuse of my viewcontroller), thankyou once again, and although a lot of these mistakes were small, I definitely learned some valuable stuff (particularly NSlogs will be very valuable down the road, I think). Thanks again.
I hate to continue, but I am having one more problem. I have started applying alerts elsewhere in the app (thankyou for helping me with that once again), but I am having a problem with the cases. In other alerts, when I choose the new alert's button representing [for instance] case 1, case 1 from the terms and conditions alert is called. Any suggestions on how to keep these actions seperate?
I hate to continue, but I am having one more problem. I have started applying alerts elsewhere in the app (thankyou for helping me with that once again), but I am having a problem with the cases. In other alerts, when I choose the new alert's button representing [for instance] case 1, case 1 from the terms and conditions alert is called. Any suggestions on how to keep these actions seperate?
Glad to hear you got the problem fixed, and learned something as well! NSLog is a really useful debugging tool.
Regarding this new issue, there's a simple solution. Before you call the show method, you can set the tag property of the alertview. Do this for each of your UIAlertView instances, and set them to a different numbers. Example: [myAlertView setTag: 1];
If you look at the delegate method you're using, you can see that it receives a reference named "alert" to the UIAlertView that's currently calling it.
The delegate method:
alright, i have tagged each alert but still am not sure if i understand what you want me to do within each method code: i need to replicate the
Code:
if (alert.tag == 1) {//}
else if (alert.tag == 2) {//}
else if (alert.tag == 3)
for each alert? that seems like a lot of unneccesary code to me. if i only need to indicate an if (alert.tag == 2) [for instance], each time, i would keep the code outside of the alert method code and just tell it to call each alert? even at that point, i am still a little foggy on how/where i would that. sorry, i know i frasing this very wierd and probably completely missing the point; i am falling asleep as i type, haha.
*edit: and while i'm asking, i am wondering you know how to rearrange the buttons into a 2 x 2 organization opposed to the 1 x 4 format that is default? i have read setNumberOfRows = 2 but it leaves me with a warning, which makes me fear any potential (way down the road) acceptance into the app store.
Glad to hear you got the problem fixed, and learned something as well! NSLog is a really useful debugging tool.
Regarding this new issue, there's a simple solution. Before you call the show method, you can set the tag property of the alertview. Do this for each of your UIAlertView instances, and set them to a different numbers. Example: [myAlertView setTag: 1];
If you look at the delegate method you're using, you can see that it receives a reference named "alert" to the UIAlertView that's currently calling it.
The delegate method:
if (alert.tag == 1) {
//It's the Terms&Condition Alert, handle it this way
}
else if (alert.tag == 2) {
//It's the Other Alert, handle it this way
}
and so on.
- kalx
scratch that last edit (about the setnumberofrows, a few minutes of searching shows it's not worth it). anyways, i am still foggy about the tagging. should i indicate each tag globally for the implementation (before the first action?)
alright, i have tagged each alert but still am not sure if i understand what you want me to do within each method code: i need to replicate the
Code:
if (alert.tag == 1) {//}
else if (alert.tag == 2) {//}
else if (alert.tag == 3)
for each alert? that seems like a lot of unneccesary code to me. if i only need to indicate an if (alert.tag == 2) [for instance], each time, i would keep the code outside of the alert method code and just tell it to call each alert? even at that point, i am still a little foggy on how/where i would that. sorry, i know i frasing this very wierd and probably completely missing the point; i am falling asleep as i type, haha.
*edit: and while i'm asking, i am wondering you know how to rearrange the buttons into a 2 x 2 organization opposed to the 1 x 4 format that is default? i have read setNumberOfRows = 2 but it leaves me with a warning, which makes me fear any potential (way down the road) acceptance into the app store.
I didn't quite understand what you said, but let me try to explaining it again further.
Lets say your app is going to have three possible AlertViews on your main screen. The three AlertViews (for example) are Terms&Conditions Alert (tag=0), About Alert (tag=1), and Warning Alert (tag=2).
Somewhere in your app, you're creating the UIAlertView. After you create it (the initWithTitle method), assign it a unique tag number using setTag (I used 0, 1 and 2 in the example above). And then at some point, you tell the alertview to show.
No matter which AlertView you run SHOW on, they all will end up calling the SAME (void)alertView: (UIAlertView *)alert clickedButtonAtIndex: (NSInteger)buttonIndex delegate method. Since all the alerts are calling this SAME method, you need a way to differentiate between the alerts. This is where the tags come in handy!
This delegate method (void)alertView: (UIAlertView *)alert clickedButtonAtIndex: (NSInteger)buttonIndex receives two parameters, a reference to the ALERT that called it, and the index of the button that was pressed.
Since you have a reference to the alert called 'alert', you can check it's tag #, and then act appropriately.
Code:
- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"Made it to the delegate method! The alert view works!");
if (alert.tag == 0) {
//Tag is 0, The Terms&Conditions Alert is the one we're handling
NSLog(@"TermsAndCondition AlertView");
switch(buttonIndex)
{
case 0:
{
NSLog(@"The first button was pressed");
break;
}
case 1:
{
NSLog(@"The second button was pressed");
SubmittingTermsViewController *submitterms = [[SubmittingTermsViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:submitterms animated:YES];
[submitterms release], submitterms = nil;
break;
}
case 2:
{
NSLog(@"The third button was pressed");
ConditionsViewController *commissionsterms = [[ConditionsViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:commissionsterms animated:YES];
[commissionsterms release], commissionsterms = nil;
break;
}
case 3:
{
NSLog(@"The fourth button was pressed");
SitewidePoliciesViewController *privacyterms = [[SitewidePoliciesViewController alloc] initWithNibName:nil bundle:nil];
[loginview presentModalViewController:privacyterms animated:YES];
[privacyterms release], privacyterms = nil;
break;
}
default:
{
NSLog(@"Something went wrong");
break;
}
}
NSLog(@"Done handling Terms&Cond AlertView")
}
else if (alert.tag == 1) {
//Tag is 1, The About Alert is the one we're handling
NSLog(@"About AlertView");
//do whatever you want for each button of the About Alert here
NSLog(@"Done handling About AlertView ");
}
else if (alert.tag == 2) {
//Tag is 2, The Warning Alert is the one we're handling
NSLog(@"Warning AlertView");
//do whatever you want for each button of the Warning Alert here
NSLog(@"Done handling About AlertView ");
}
else {
//The alert tag wasn't 0,1,2 so don't know how to handle it
}
NSLog(@"Now we're leaving the delegate method. Did anything happen?");
}
So in this delegate method, we perform the proper action for each button, depending on which AlertView we're handling.
Hope that helps. I'm not sure about your second question regarding the button arrangement, but good luck getting everything working!