alertView didDismissWithButtomIndex is not called after a click on the alertView's buttom - iphone

I have recently begun my studies on iOS development so forgive me if I am asking something too obvious.
When my application's view loads it checks the configurations for some keys and if there's no value for these keys the application should display an alert and quit.
First of all, I have implemented the UIAlertViewDelegate:
#interface FirstViewController : UIViewController <UIAlertViewDelegate> {
...
And then checked for the settings:
- (void)viewDidLoad {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *url = [defaults stringForKey:#"url"];
NSString *apiKey = [defaults stringForKey:#"api-key"];
if([url length] < 1 || [apiKey length] < 1){
UIAlertView *dialog = [[[UIAlertView alloc]
initWithTitle:#"Not properly configured"
message:#"This application was not properly configured. Please configure the application on your iPhone settings."
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil]
autorelease];
[dialog setTag:1];
[dialog show];
}
[url release];
[apiKey release];
[super viewDidLoad];
}
I understand that the method alertView didDismissWithButtomIndex should be called after the alertView's dismiss but for some reason this method is never called in my code.
- (void)alertView:(UIAlertView *)alertView didDismissWithButtomIndex:(NSInteger)buttomIndex {
if([alertView tag] == 1){
exit(0);
}
}
Any ideas on why this is happening?

didDismissWithButtonIndex is misspelled, you snuck an ‘m’ in there instead of ’n’.

You are listening for the wrong method, you should implement :
alertView:clickedButtonAtIndex:
In the doc you can read that the didDismissWithButtomIndex is called when dismissWithClickedButtonIndex:animated: is called on the alertView.
alertView:didDismissWithButtonIndex:
Sent to the delegate after an alert view is dismissed from the screen.
So for your code to work you should implementsomething like :
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(buttonIndex == ...) {
// do something
}
}
PS: You shouldn't call exit(0), it is a bad practice on iOS to force an application to quit. User are supposed to quit the app with the home button.

Related

Show UIAlertView after UIActionSheet button pressed

After the user clicks a button I want an action sheet to come up asking for them to choose between two options. Once they have selected an option, I want an AlertView to come up telling them they will leave the application and have them choose to cancel to operation or continue to the other application.
Code is as follows:
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface mapView : UIViewController <MKMapViewDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
#property (nonatomic, weak)IBOutlet MKMapView *mapView;
#property (nonatomic, weak)IBOutlet UIBarButtonItem *getDirections;
- (IBAction)selectDestination:(id)sender;
- (void)checkLeave;
#end
.m
- (IBAction)selectDestination:(id)sender
{
UIActionSheet *selectDestinationAS = [[UIActionSheet alloc] initWithTitle:#"Select Destination: " delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Destination 1", #"Destination 2", nil];
[selectDestinationAS showInView:self.view];
}
- (void)checkLeave
{
UIAlertView *checkLeaveAlert = [[UIAlertView alloc] initWithTitle:#"Leave CDSI?" message:#"This will open the Maps application to continue directions. Are you sure you want to continue?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Open", nil];
[checkLeaveAlert show];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self checkLeave];
if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString: #"Destination 1"]) {
NSURL *BOHMDirections = [NSURL URLWithString:#"http://maps.apple.com/?daddr=Destination1&saddr=Current+Location"];
[[UIApplication sharedApplication] openURL:BOHMDirections];
} else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString: #"Destination 2"]) {
NSURL *BOPDirections = [NSURL URLWithString:#"http://maps.apple.com/?daddr=Destination2&saddr=Current+Location"];
[[UIApplication sharedApplication] openURL:BOPDirections];
}
}
The ActionSheet shows up, when an option is selected the Maps app opens (as desired) but the AlertView shows up only after you reenter the original app. How do I get it to show up before I leave the app?
Navigate to the external app on UIAlertView delegate.
To pass the selected item index at UIActionSheet, pass the index as parameter in checkLeave method and set as tag to the UIAlertView
By this way, the UI execution will be, on ActionSheet Clicked, the alertview ask confirmation with user. Once the user confirms, the navigation will be performed based on the action sheet selection. To hold, the action sheet selection, we are passing that data as tag.
If you need, you can add a private property to hold the item data clicked and access it in UIAlertViewDelegate.
- (void)checkLeave :(NSInteger)index
{
UIAlertView *checkLeaveAlert = [[UIAlertView alloc] initWithTitle:#"Leave CDSI?" message:#"This will open the Maps application to continue directions. Are you sure you want to continue?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Open", nil];
[checkLeaveAlert setTag:index];
[checkLeaveAlert show];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self checkLeave : buttonIndex];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 1){
//Destination 1 clicked
}
}
Similar to the action sheet, UIAlertView has a delegate protocol that you should implement/comply with. Especially the method alertView:didDismissWithButtonIndex: is of interest.
Call the Maps app there and not in clickedButtonAtIndex

iPhone / iPod Button in background shearing through to UIAlertView TextBox

As I type into a textbox on a UIAlertView, an ImageButton in the background starts shearing through. It only happens when the text gets close to the image.
The code for the alertview is as follows:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"... number"
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
[alert setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[alert textFieldAtIndex:0] setKeyboardType:UIKeyboardTypeNumberPad];
[[alert textFieldAtIndex:0] becomeFirstResponder];
[alert setTag:1];
[alert setOpaque:true];
[alert show];
//EDIT
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 2)
{
NSString* title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"Cancel"])
{
[self doSomething1];
}
if([alertView.title isEqualToString:#"Are you sure?"] && [title isEqualToString:#"YES"])
{
[self doSomething2];
}
}
}
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
if (alertView.tag == 1){
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if( [inputText length] == 10 )
{
NSUserDefaults* def = [NSUserDefaults standardUserDefaults];
[def setObject:inputText
forKey:#"FIELD"];
[def synchronize];
return YES;
}
else
{
return NO;
}
}
return YES;
}
I have tried setting it to opaque, I have tried looking for z-indexing values, and I have also tried scaling the image down to the smallest it needs to be. Taking screenshots does not help. This only happens in iOS 7.
UIAlertView are not shown in the same UIWindow as the rest of your view controllers. They are shown in their own UIWindow with a windowLevel of UIWindowLevelAlert. This other window is transparent (mostly) and renders on top of your main window. This makes UIAlertView objects not interact as well with other views you may have on screen. Do not modify any properties from the underlying UIView class.
The code you show above has if (alertView.tag == 1) as well as if (alertView.tag == 2), but it only ever creates a UIAlertView with a tag value of 1. Is there somewhere else you are creating a second alert? Are you possibly showing a second alert before the first one completes its disappearance animation? That has been known to cause graphical tears.
The delegate method -alertViewShouldEnableFirstOtherButton: can be called from within the -drawRect: method of the UIAlertView. The draw method must be extremely fast to avoid causing graphical tearing. Yours calls NSUserDefaults -synchronize, which performs a disk write operation. You should not perform any operation within your -alertViewShouldEnableFirstOtherButton: method, besides determining the response value. If you want to be notified of changes to the text field, assign yourself as the UITextFieldDelegate and implement -textField:shouldChangeCharactersInRange:replacementString:. That method should be safe to call NSUserDefaults -synchronize from.
As an additional tip, you could make your code much easier to manage using the PSPDFAlertView.

How to navigate from app delegate class in window based iPhone application. How to write pushViewcontroller method in app delegate class

In my window base application I need to navigate to informationview from my appdelegate when i click on alert view button.
alert view works with NSlog.
But i need to push to the other view for this purpose i used
[self.navigationController pushViewController:info animated:YES];
but it doesn't pushes. just nslog only prints
- (void)applicationDidBecomeActive:(UIApplication *)application
{
//To count the number of launches
NSInteger i = [[NSUserDefaults standardUserDefaults] integerForKey:#"numOfCalls"];
[[NSUserDefaults standardUserDefaults] setInteger:i+1 forKey:#"numOfCalls"];
NSLog(#"the number of active calls are %d",i%3);
if(i%3==0 && i!=0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"you might prefer MedChart+" message:#"Get it now for more options" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert show];
[alert release];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"canceled");
}
else if (buttonIndex == 1)
{
NSLog(#"Pushed to the information view ");
InformationViewCotroller *info = [[InformationViewCotroller alloc]initWithNibName:#"InformationViewCotroller" bundle:nil];
[self.navigationController pushViewController:info animated:YES];
}
}
(dont consider 'i' values it is part of my logic).
Thanks in advance
Before Navigate to any viewController , set the RootController for your navigationController of appDelegate.
Add navigationController.View as subview of window.Then your root controller will be the first ViewController.from there you can push to any viewController.

UIAlertViewStylePlainTextInput - Program continues without waiting for text input from user

I'm sort of stuck on a UIAlertViewStylePlainTextInput. (My code is too long to post here, but this is the part where the problem exists.) It all sort of works, but the program doesn't wait until the user enters the information before continuing. The "editName" button doesn't change the display in the code below, but the updateDisplay button works fine (if you've pressed the "editName" button before you pressed "updateDisplay"). How can I get everything to sort of halt until the user enters the info (or cancels). Or is there some other lead that will take me where I need to go. (I've been toying with putting the rest of the code in the -(void) alertView, but that just doesn't seem to be the correct way of doing it).
Thanks in advance.
#import "HSTestViewController.h"
#implementation HSTestViewController
#synthesize display;
NSString *newName;
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
newName = [[alertView textFieldAtIndex:0] text];
}
}
- (void) getNewName;
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You made the High Score List"
message:#"Please enter your name"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
- (IBAction)editName:(id)sender
{
[self getNewName];
newName = display.text;
}
- (IBAction)updateDisplay:(id)sender
{
display.text = newName;
}
#end
Add UIAlertViewDelegate to the class. And implement the below delegate method.
OK button index value will be 1 in your case.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex)
{
// call the method or the stuff which you need to perform on click of "OK" button.
}
}
Hope this helps.

Get immediate value from UIALertView

I have what can be most accurately described as a Factory, which is generating some NSOperations. Before the NSOPerations are generated, I would like to check the current network status and, if the user is on a 3G/Mobile connection, warn them that they are about to do a data-heavy operation.
I attempted to do this with a UIAlertView, but the only way I can see to get the "response" from a UIAlertView is via the event-based delegate system. I was wondering if there was any way to have it act like the "confirm" dialogue in JavaScript, where it blocks the UI and I can get an immediate value from it once it is dismissed.
Is there any standard way to do this, or some example code I could be pointed towards that accomplishes something similar?
Blocking the main thread is considered bad practice on iOS, and thus there is no synchronous API for UIAlertView.
You should implement a delegate callback for the alert that enqueues the relevant NSOperation. It may be useful to subclass UIAlertView to store the relevant data you need to enqueue the NSOperation, or better yet store a block that captures the relevant variables and then just execute that when the user confirms the dialog.
You can implement something similar to that, using blocks. The execution will continue as in all other cases, but the flow of reading your code might more resemble what you want. Here is a helper class that I made for that purpose so that I can just go:
[YUYesNoListener yesNoWithTitle:#"My Title" message:#"My Message" yesBlock:^
{
NSLog(#"YES PRESSED!");
}
noBlock:^
{
NSLog(#"NO PRESSED!");
}];
...and here is the helper class:
typedef void(^EmptyBlockType)();
#interface YUYesNoListener : NSObject <UIAlertViewDelegate>
#property (nonatomic, retain) EmptyBlockType yesBlock;
#property (nonatomic, retain) EmptyBlockType noBlock;
+ (void) yesNoWithTitle:(NSString*)title message:(NSString*)message yesBlock:(EmptyBlockType)yesBlock noBlock:(EmptyBlockType)noBlock;
#end
#implementation YUYesNoListener
#synthesize yesBlock = _yesBlock;
#synthesize noBlock = _noBlock;
- (id) initWithYesBlock:(EmptyBlockType)yesBlock noBlock:(EmptyBlockType)noBlock
{
self = [super init];
if (self)
{
self.yesBlock = [[yesBlock copy] autorelease];
self.noBlock = [[noBlock copy] autorelease];
}
return self;
}
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0 && self.noBlock)
self.noBlock();
else if (buttonIndex == 1 && self.yesBlock)
self.yesBlock();
[_yesBlock release];
[_noBlock release];
[alertView release];
[self release];
}
- (void) alertViewCancel:(UIAlertView *)alertView
{
if (self.noBlock)
self.noBlock();
[_yesBlock release];
[_noBlock release];
[alertView release];
[self release];
}
+ (void) yesNoWithTitle:(NSString*)title message:(NSString*)message yesBlock:(EmptyBlockType)yesBlock noBlock:(EmptyBlockType)noBlock
{
YUYesNoListener* yesNoListener = [[YUYesNoListener alloc] initWithYesBlock:yesBlock noBlock:noBlock];
[[[UIAlertView alloc] initWithTitle:title message:message delegate:yesNoListener cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil] show];
}
#end
Using the code of Ricky Helgesson, I've built a Pod component to use this solution easily in any project that uses CocoaPods.
https://github.com/nmaletm/STAlertView
The code that you should use is:
[[STAlertView alloc] initWithTitle:#"Title of the alert"
message:#"Message you want to show"
cancelButtonTitle:#"No" otherButtonTitles:#"Yes"
cancelButtonBlock:^{
// Code todo when the user cancel
...
} otherButtonBlock:^{
// Code todo when the user accept
...
}];
And add at the Podfile:
pod "STAlertView"
There are more instructions at the github page.