How to handle sender tag in Alert View - ios5

I am very new to iOS development. I have the following method done by another developer
-(IBAction)btnDelete:(UIButton *)sender
{
indexOfBlockedFriend=sender.tag-50;
[self deleteFriend];
}
I want to show an alert view before the delete action is performed. How do I do that.

To handle AlertView button click, you have to conform to UIAlertViewDelegate protocol.
in your.h
#interface YourViewController:UIViewController<UIAlertViewDelegate>{
.......
.......
}
Then implement UIAlertViewDelegate protocol methods,
in your.m
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
//cancel clicked ...do your action
}else if (buttonIndex == 1){
//reset clicked
}
}

With the UIAlertView class
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hello World" message:#"Hello" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
If you want to have more than one option you will need to become the delegate for the alert to get a callback for which button was touched. Delegation is a concept of Object Oriented Programming (OOP) that you will have to become familiar with.
EDIT:
You may be interested in block-based UIAlertViews. The one that I use in a lot of projects is called UIAlertView+MKBlockAdditions. It contains easy methods for handling all the alert delegate logic in a block handled by the alert.

Related

UIAlertViewDelegate not acting as expected

I have a very simple process running where after each round of a simple game the scores are calculated, labels updated and all the normal, very simple stuff. I have a UIAlertView that informs the player of how s/he performed. I use a UIAlertViewDelegate to postpone all the updates, resetting of controls etc. till after the UIAlertView is dismissed. The methods are [startNewRound],[startOver] and [updateLabels]. It's fairly obvious what they all do. Anyway, when the user hits round ten, I've made another UIAlertView that informs the player that the game has ended and shows the overall score. Again, I hoped to use a delegate to postpone the resets till after the AlertView is dismissed. The only problem is, with the endGame AlertView, it seems to be using the first AlertView's delegate method causing the game to continue with a new round and not start from the beginning. I hope this makes sense. Anyway, here are snippets of my code.
if (round == 10){
UIAlertView *endGame = [[UIAlertView alloc]
initWithTitle: #"End of Game"
message: endMessage
delegate:self
cancelButtonTitle:#"New Game"
otherButtonTitles:nil];
[endGame show];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: title
message: message
delegate:self
cancelButtonTitle:#"Next"
otherButtonTitles:nil];
[alertView show];
}
And then the delegate methods:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[self startNewRound];
[self updateLabels];
}
- (void)endGame:(UIAlertView *)endGame didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[self startOver];
}
So there it is. As I mentioned, the endGame AlertView appears to be using alertView's delegate, thus not activating the [self startOver] method. All the methods are working, it's just the AlertView is using the incorrect delegate method. Regards, Mike
Change your code like this,
if (round == 10){
UIAlertView *endGame = [[UIAlertView alloc]
initWithTitle: #"End of Game"
message: endMessage
delegate:self
cancelButtonTitle:#"New Game"
otherButtonTitles:nil];
endGame.tag = 111;
[endGame show];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: title
message: message
delegate:self
cancelButtonTitle:#"Next"
otherButtonTitles:nil];
alertView.tag = 222;
[alertView show];
}
and delegate method as,
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 111)
{
[self startNewRound];
[self updateLabels];
}
else if(alertView.tag == 222)
{
[self startOver];
}
}
You cant have two delegate method for dismisswithbuttonindex, you need to handle this situation with tag.
Give both alert view a different tag and check it on delegate object. Thus you can differentiat the both alert view.

How the UIActionSheet works?

When popping a view I want to save some data, by asking confirmation. I'm asking confirmation using UIActionSheet. But irrespective of my response in action sheet, the view is changing in background, it creates some problem for me to use the response. I'm using navigation controller to switch views. How can I solve this
TIA
Better option is to use uialertview for asking confirmation.To do this follow this step:
Insure your header file contains the following:
#interface YourViewController : UIViewController <UIAlertViewDelegate>
Now when asked confirmation add this code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Message" message:#"Are You Sure" delegate:self cancelButtonTitle:#"YES" otherButtonTitles:#"NO", nil];
[alert show];
[alert release];
Now after pressing one button below delegate will be called so add in .m file of app
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the YES/NO buttons
if (buttonIndex == 0)
{
NSLog(#"NO button pressed");
}
else
{
//Save data here
NSLog(#"YES button pressed");
}
}
#PooLas If I understood you correctly, You use uiactionsheet for user confirmation, while in background (actually under actionsheet) you change view controllers. Well, you can't do that, because delegate must be attached to controller which shows it up (if i am wrong, correct me). So when you click button, you can only first dismiss actionsheet and then change view controller, but not opposite – PooLaS

Detecting button pressed when there are multiple alert views

I have multiple alert views in one view, and I use this code to detect which button was pressed:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"OK"]) {
//for one alert view
[passCode becomeFirstResponder];
} else if ([title isEqualToString:#" OK "]) {
//for another alert view, had to change "OK" to " OK "
[passCodeConfirm becomeFirstResponder];
}
}
Now since there are multiple alert views in one view that do different things, I have to trick the user into thinking "OK" and " OK " are the same thing. It works and looks fine, but it feels kind of messy. Surely there is another way to do this, such as making this specific to an alert view, and then making it specific to another. Do you know how I would do this? Thanks!
It would be more technical as well better that set unique tag for separate UIAlertView and identify it and access in its delegate method.
For example,
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Message" message:#"Are You Sure you want to Update?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert setTag:1];
[alert show];
[alert release];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 1)
{
// set your logic
}
}
Use tag property to uniquely identify each of the alertview u create.
Like this
myAlertView.tag = 1
Then in the clickedButtonAtIndex delegate method check which alertview's button was clicked using this tag property ,
if(alertView.tag==1)
I wouldn't use the titles to distinguish between the buttons. You'll run into problems when your app is localized or you decide to change the button titles, but forget to update them everywhere. Use the button indexes instead or if you only have one button in addition to a cancel button, use the cancelButtonIndex property of UIAlertView.
To distinguish between multiple alert views, you could use their tag property.
In your view, add a property for each alert view.
UIAlertView *myAlertType1;
UIAlertView *myAlertType2;
#property (nonatomic, retain) UIAlertView *myAlertType1;
#property (nonatomic, retain) UIAlertView *myAlertType2;
Create your alert using these properties
self.myAlertType1 = [[[UIAlertView alloc] initWithTitle: ... etc] autorelease];
[self.myAlertType1 show];
Then in your delegate method:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView == myAlertType1) {
// check the button types and add behaviour for this type of alert
} else if (alertView == myAlertType2 {
// check the button types and add behaviour for the second type of alert
}
}
Edit: Although the above works, iApple's suggestion of using the tag seems cleaner/simpler.
//in your .h file
UIAlertView* alert1;
UIAlertView* alert2;
//in your .m file
// when you are showing your alerts, use
[alert1 show]; //or
[alert2 show];
//and just check your alertview in the below method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView == alert1)
{
//check its buttons
}
else //check other alert's btns
}

UIViewController doesn't get deallocated after being popped from a navigation controller, if the action starts from a UIAlertView delegate

would you please look at that piece of code:
/* This app is a game, the user can click an "abort" button anytime,
* and he/she is therefore asked for confirmation ("really abort game?")
*/
- (IBAction)btnAbortClicked:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setMessage:#"Really abort game?"];
[alert setDelegate:self];
[alert addButtonWithTitle:#"Yes"];
[alert addButtonWithTitle:#"No"];
[alert show];
[alert release];
}
/* Delegate method (I don't like it, I wish I had modal blocking windows) */
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0)
[self quitGame];
}
/* pop the view controller */
- (void)quitGame {
[self.navigationController popToRootViewControllerAnimated:YES];
}
The problem is simple - but apparently not enough for me to solve. The UIViewController gets popped, but doesn't get deallocated. And the problem is strictly related to the UIAlertView, because if I just call quitGame from btnAbortClicked:, the view controller is popped and immediately deallocated.
Instead, it seems some mysterious entity retains it.
Can you help me? Thanks in advance.
Well, I think that you're still inside the alertView when clickedButtonAtIndex is called. I'd suggest moving to alertView:disDismissWithButtonIndex instead, so that you're called after the alertview disappears.

How to immediately force view to draw itself after closing Alert View by the user?

the situation is like this:
if i don't have internet connection, i show UIAlertView to the user.
when the user press "try again", i call "do something".
the problem is the UIAlertView still show for seconds.after the user click "try again"
i tried like:
[self.view setNeedsDisplay];
but,it not works, cause even in the documents,if said the refresh will be
only when code control will return to the system, and that is not the case here.
thanking in advance.
///////////////////////////////////
if(somecondition)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"NO INTERNET CONNECTION"
delegate:self cancelButtonTitle:nil otherButtonTitles:#"Try Again", nil];
[alert show];
[alert release];
return;
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
[self DoSomthing];
}
I use this method to detect when the alert is dismissed, I added a line of code to hide it and spawn a new URLrequest, if that's what you need.
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
alert.hidden=YES;
[webnews loadRequest:[NSURLRequest requestWithURL:home]];
}
The request uses my UIWebView 'webnews' and the NSURL 'home', you will have to adapt these of course.
If you do some lengthy process in the callback from the alert, it will not hide until that callback returns.
So in other words, your doSomething method should not directly try to reconnect to the internet, but just have it spawn off the asynchronous call for doing this.
EDIT:
You may delay/detach execution of doSomething with this line of code:
[self performSelector:#selector(doSomething) withObject:nil afterDelay:0];