how to return a number from UIAlertView - objective-c

I have a function like
I want getResponse to return the index of the button pressed.
-(NSNumber*)getResponse
{
...
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Title"
message:#"Message"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Si",nil];
[alert show];
return """Index of button Pressed"""
}
getResponse looks prefUser data in order to return a number 0 or 1 but there are some combinations that are to be asked to the user in order to know what to return.
User may check allways save data (so it returns 1)
Or may check never save data (...returns 0)
Ask me every time:
It's like:
¿do you want to save the data? (YES/NO)

You can use delegate method, first set up view controller as UIAlertViewDelegate:
#interface YourClass : UIViewController <UIAlertViewDelegate>
and add that delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
// button index it what you are looking for
}

Related

Why is the UIAlertView not blocking until user responds by tapping a button?

In my iOS 7 app, I need to verify the user wants to deleta a selected record from Cord Data. I have the UIAlertViewDelegate defined in the .h file. This is the code to display the alert:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
[alert show];
if(alertButtonTapped == 0)
return;
// remainder of code to delete record follows (was omitted)
This is the code to check which button was tapped:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
alertButtonTapped = [NSNumber numberWithInteger:buttonIndex];
return;
}
The problem is the alert is displayed and then immediately falls through the remainder of the code in that method. I have never seen this before; usually it blocks until the user has responded by tapping one of the buttons (at least I thought it did). What do I need to do to make this alert block until the user responds? (I was looking at UIAlertView blocks, but not sure that would do the job since it appears to use a different thread)
This is how UIAlertView works -- it doesn't block, thus why it has the UIAlertViewDelegate methods for actually implementing a response.
If the "remainder of code" is what should happen after they tap a button (e.g. the "Delete" button), then move all of that code into the delegate method, like:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
EDIT - adding example to answer a comment
So if you have multiple UIAlertViews in the same class, you could differentiate between them using the tag attribute of UIView (UIAlertView is-a UIView). So it could be something like this:
const NSInteger kDeleteAlertTag = 100; // declared at the top of your .m file, perhaps.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:#"Are you sure you want to delete this record?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
alert.tag = kDeleteAlertTag;
[alert show];
Then your delegate response might look like this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.tag == kDeleteAlertTag) {
if (buttonIndex != alertView.cancelButtonIndex) {
// code to delete record
}
}
else if (alertView.tag = kDoSomethingElseAlertTag) {
DoSomethingElse();
}
}

How to show an alert before leaving the table view.?

I am working with a master detail application. In the master section records are listed, and detail section shows each record details. The detail section is a table view where we can edit each record. the problem is that "while editing a record,if i tap a record on the other side, any changes that i have made on the original record are lost and new record details are shown in the table view"...
can anyone please tell me how to show an alert that asks for "save or cancel" , before "showing the new record details"..
any changes that i have made on the original record are lost
A common rule in developing applications is
NEVER loose the user's work
So it would maybe just be the best idea to just save what the user changed.
But let's head to your actual question:
can anyone please tell me how to show an alert
I think you mean those alters looking like push notifications with two buttons.
You create them with UIAlertView.
Then in the alert's delegate you can figure out which button was pressed and you can decide how to go on. Just check out the documentation for UIAlertView - it's pretty simple :)
try this,
-(void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:LString(#"ISCO_FLOW_CALC") message:LString(#"DELETE_MESSAGE") delegate:self cancelButtonTitle:LString(#"CANCEL") otherButtonTitles:LString(#"SAVE"), nil];
alert.tag=11;
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(buttonIndex==1 && alertView.tag==11)
{
//your save data action;
}
if(buttonIndex==0 && alertView.tag==11)
{
//your Cancel data action;
}
}
Keep a reference to your DetailViewController in the MasterViewController
eg. in your MasterViewController.h:
DetailViewController *detailVC;
Set this reference to your most recent DetailViewController in didSelectRowAtIndexPath and always check if it is not nil before showing a new detailVC
DetailViewController *controller=[[DetailViewController alloc] init]; //Or similar
if (detail){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Save or Cancel" message:#"Save or Cancel" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Save",nil];
[alert show];
}
else{
detailVC=controller;
//Show controller
}
Now show the new detailViewController after the user tapped a button of the UIAlertView:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0) { //Tapped cancel
//show detailVC
}
else{ //Tapped save
//save
//Show detailVC
}
}
Hope this helps

confirmation before open in safari

Im trying to add a UIAlertView to warn the user that the link will open in Safari. The user can then choose OK(open the url) or cancel which should just close the alert and return to the links.
I have three different UIButtons which has 3 different URLs.
Right now ive added a IBAction to all buttons and all buttons has Tags (which i think i can use somehow :D). I guess - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: delegate will be good to use to..
My question: how should the UIAlertView know what URL to open i user clicks ok?
I suggest that you use a subclass of UIAlertView that is able to track some more properties along. I do this in all my projects and it is much simpler.
One solution to do this would be to subclass UIAlertView to MyAlertView and add a #property(nonatomic, retain) id userInfo; or #property(nonatomic, retain) NSURL* urlToOpen. Thus you can attach custom data to your UIAlertView and retrieve it in the delegate method to do whatever you need with it.
Another solution, and my preferred one actually, is to add Objective-C blocks support to UIAlertView, to be able to use UIAlertView using the blocks API instead of using a delegate. This is particularly useful if you use multiple UIAlertViews in the same class and with the same delegate, as using a single delegate to handle the different instances is a mess.
I personally use this technique all the time, as it also makes my code more readable by having the code that executes when the button is tapped right next to the code that shows the alert, instead of having it at a complete different places when you use delegate methods.
You can look at my OHAlertView subclass here on GitHub that implement this already. The usage is really simple and allow you to use blocks for each alert view instead of a common delegate, see below.
Usage Example
-(void)confirmOpenURL:(NSURL*)url
{
NSString* message = [NSString string WithFormat:#"Open %# in Safari?",
url.absoluteString];
[OHAlertView showAlertWithTitle:#"Open URL"
message:message
cancelButton:#"No"
okButton:#"Yes"
onButtonTapped:^(OHAlertView* alert, NSInteger buttonIndex)
{
if (buttonIndex != alert.cancelButtonIndex)
{
// If user tapped "Yes" and not "No"
[[UIApplication sharedApplication] openURL:url];
}
}];
}
Then each button can have its own action:
-(IBAction)button1Action
{
[self confirmOpenURL:[NSURL URLWithString:#"http://www.google.com"]];
}
-(IBAction)button2Action
{
[self confirmOpenURL:[NSURL URLWithString:#"http://www.stackoverflow.com"]];
}
Or you can have a common IBAction for all your buttons opening URLs:
-(IBAction)commonButtonAction:(UIButton*)sender
{
NSUInteger tag = sender.tag;
NSString* urls[] = { #"http://www.google.com", #"http://www.stackoverflow.com" };
NSURL* buttonURL = [NSURL URLWithString: urls[tag] ]; // in practice you should check that tag is between 0 and the number of urls to be sure, that's just an example here
[self confirmOpenURL:buttonURL];
}
Solved it like this:
added a tag when creating the UIAlertView. Like this:
- (IBAction)PressedButton {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Link"
message:#"Want to open in safari?"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
message.tag = 2; //different tag for each button
[message addButtonWithTitle:#"Cancel"];
[message show];
}
Then when - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex delegate was thrown I did this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == alertView.cancelButtonIndex){
if (alertView.tag == 1)
{
//go to URL1
}
else if (alertView.tag == 2)
{
//go to URL2
}
else if (alertView.tag == 3)
{
//go to URL3
}
}
}
Your button action method should have a signature like this:
-(void)doSomething:(id)sender;
whereby sender will be the button. Based on this you could find out which URL is meant.

how to connect UIAlertView with what happens when the user makes a choice?

I have code setting up a UIAlertView:
-(IBAction)showMessage
{
//NSInteger *buttonIndex = NULL;
UIAlertView *message = [[UIAlertView alloc] initWithTitle:nil
message:nil
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Email",#"SMS",#"Facebook",#"Twitter", nil];
[message show];
}
and code explaining what to do once the user makes a choice:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1){
[self openMail];
}
else if (buttonIndex == 2)
//etc.
}
But what I can't figure out is how to connect the two. The obvious answer is to add a line to the first piece of code calling alertView: clickedButtonAtIndex on UIAlertView *message, but how do you assign buttonIndex? How do you tell alertView whether the user has chosen Facebook, Email, etc?
Add to the header file if you haven't already:
#interface YourClass : UIViewController <UIAlertViewDelegate>
{
}
...etc
and in your AlertView code change delegate:nil to delegate:self
For more information have a look at the Apple Docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
From the docs:
The button indices start at 0. If this is the cancel button index, the alert view is canceling. If -1, the cancel button index is not set.
(1) You want to set delegate:self when you initialize the message. Also, in your interface declaration, do something like:
#interface myClass: UIViewController <UIAlertViewDelegate>
This way, your handler function automatically gets called when the user makes a selection.
(2) Buttons are indexed in the order you listed them.
(3) Since you have a lot of options for the user to choose from, it is better to use UIActionSheet instead of UIAlertView. Alerts are generally used for simple Yes/No-type selections.
Hope this helps!

Open AlertView before calling method

I'd like to call a method
[self someMethod:bar]
But how can I open an AlertView before? someMethoud should wait for AlterView OK-Button. Do i need to write a complex task manager? Or is there a smart solution?
display the alert, and when the user clicks the button, then call your method.
remember to add the delegate to your class
#interface YourViewController : UIViewController <UIAlertViewDelegate>
code in your controller
// display the alert
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Message"
delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
// UIAlertViewDelegate method - get the click here and take action
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
// ok button pushed
[self someMethod:bar];
}
}
You would need to implement the delegate method didDismissWithButtonIndex here http://developer.apple.com/library/ios/ipad/#documentation/UIKit/Reference/UIAlertViewDelegate_Protocol/UIAlertViewDelegate/UIAlertViewDelegate.html
The, depending on the button that was tapped, you would call your method.