UIAlertView Show causing strange behavior with UIButton - objective-c

I basically have a replica of the iMessage app, but I am getting a strange behavior that the Send button is reverting back to the down position (When keyboard now showing), when I present a UIAlertView.
If I comment out [alert show], the Send button doesn't disappear.
If I do [alert show] the UIButton disappears behind the keyboard.
In the - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex I can press the cancelButton which causes no code in the method to execute, and the button will still disappear.
The only way I can get it to maintain its position is to manually put it back in that position in the - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex. There is no code about the Send UIButton either in any of the UIAlertView delegate methods except when I manually set it's frame back to the correct position.
Is this just a bug in iOS7 or is it something I am doing wrong?
Thanks!

Related

UIActionSheet in iOS7 dismissing when user taps ANYWHERE on the screen on iPhone

I've noticed that in iOS 7 a **UIActionSheet** automatically dismisses when a user taps anywhere on the screen on an **iPhone**. This was NOT the case in iOS 6 and is leading to unintended effects. Is this a UI change? Bug? Is there a way to disable this?
From iOS 7 docs: "As described in iOS human interface
guidelines, you should include a Cancel button with action sheets
displayed on iPhone and with those displayed on iPad over an open
popover. Otherwise on iPad, action sheets are displayed within a
popover, and the user can cancel the action sheet by tapping outside
the popover, in which case you do not need to include a Cancel
button."
This seems to suggest that the behavior of dismissing when tapping anywhere outside the action sheet should only pertain to iPads. But this is now happening on an iPhone running iOS 7 when it doesn't on an iPhone running iOS 6
Regarding your question Is this a UI change? Bug?
It is seems like an UI change not a bug how can I say that ? Have a look at the image i took from iOS7 simulator
It is a image of Maps application of iPhone.
When you click on button ( display in red rectangle ) one action sheet will display which have Cancel button like below
And if you click any where else it will close, same behaviour also found in other Apple applications also like safari.
Regarding your question Is there a way to disable this?
Sorry but i don't have answer for that.
A word before I post my solution. It is very easy to fear a minor change in behavior and to want to disable it right away. But consider first consistency. This is how action sheets behave across the operating system. If you disable this behavior, you will break consistency and this will result in a subpar experience for your users.
That said, here is my solution.
UIActionSheet on iPhone opens its view in a separate UIWindow instance which becomes key when it is shown. You can access this window using [UIApplication sharedApplication].keyWindow. If you inspect the view hierarchy of this window, you will notice several private classes such as dimming view. You can recursively traverse this view hierarchy and set view.userInteractionEnabled = NO; to every view there that is not a subclass of UIButton. This should do the trick.
As #nvrtdfrst implies in his comments, setting cancelButton: nil will get rid of the default dismissal behavior. But you can still have a cancel button by setting the text for one of the custom buttons to #"Cancel"--to be treated by the delegate method, something like this:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:#"Cancel"]) {
// your cancellation code here
}
}
A bit hacky, but that's a simple solution.
H/T: null.
Use
- (void)actionSheet:(UIActionSheet *)actionSheet
didDismissWithButtonIndex:(NSInteger)buttonIndex {...}
This worked for me.
(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
[self performSegueWithIdentifier:#"firstOption" sender:self];
}else if (buttonIndex == 1){
[self performSegueWithIdentifier:#"secondOption" sender:self];
} else if (buttonIndex != 0 || buttonIndex != 1) {
[actionSheet cancelButtonIndex];
}
}

Can't type in UITextField if presentViewController while editing

I have a ConfigureViewController that contains some UIButtons and a UITextField * MyTextField. Each of the buttons, when pressed, brings up a dialog-style viewcontroller using presentViewController:animated:completion:. However, if I tap one of those buttons while editing the text field, when i close the dialog and return to the original screen, i am unable to return focus to or type in the text field.
This is the method that is invoked when the button is tapped.
-(void)AdvancedInfoButtonPressed :(id)sender
{
AdvancedInfoPopViewController *myAdvancedInfoViewController = [[AdvancedInfoPopViewController alloc] init];
[myAdvancedInfoViewController setDelegateAndDevice :self :Current_Device];
myAdvancedInfoViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController :myAdvancedInfoViewController animated :NO completion :nil];
}
Without explicitly removing focus from MyTextField, presenting the AdvancedInfoViewController does dismiss the keyboard automatically.
I suspect the problem is that MyTextField still thinks it has focus (even though the keyboard and blinking cursor have disappeared) and so does not allow itself to become the first responder again. Along these lines, I have found that if i add [MyTextField resignFirstResponder] before presenting the dialog viewcontroller, the problem goes away.
However, this does not seem like a very good solution because it means having to remember to resign this textfield (or any other text fields) as the first responder in several places (leading to code that is difficult to maintain). My question is: are there any events i can hook into either when ConfigureViewController is about to be partially obscured by AdvancedInfoViewController (or when AdvancedInfoViewController is dismissed and focus is returned to the ConfigureViewController) in which i can add some logic to clean up MyTextField's firstResponder status?
I've tried viewWillDisappear and viewWillAppear but they are never called on the ConfigureViewController.
I've also tried adding textFieldDidEndEnding to the text field's delegate but, despite it being called, it did not fix the problem.
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[MyTextField resignFirstResponder];
}
You can use [self.view endEditing:YES] to resign all first responders in the case you are presenting myAdvancedInfoViewController.
To return focus to the textField after this event occurs you will need to keep track of which textField was active at the time myAdvancedInfoViewController was presented. When the myAdvancedInfoViewController is dismissed call UITextField's becomeFirstResponder method for the appropriate text field.

iOS Beginner: UIAlertView Window with 3 Buttons > Check what button was pressed

I have a working code from a tutorial but don't understand it completely.
Situation:
After a button was pressed in my iPhone App
an AlertView appears with three buttons.
Now I like to check what button the user pressed.
CODE FROM THE TUTORIAL:
- (IBAction)infoButtonPressed:(id)sender {
UIAlertView *myAlert1 = [[UIAlertView alloc]initWithTitle:#"My Alert View 1"
message:#"Here we go"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Option1", #"Option2", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex);
}
Code works, I see the correct output in the console as a NSLog but how is it possible
that the method:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex);
}
refers to the correct alert view. In this case: myAlert1.
What about with more than one alert view.
For example a second one calling myAlert2.
I know the following code is not correct but it would make more sense to me
if I'd write the method as follow:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Button: %i, was pressed.", buttonIndex_FROM_myAlert1);
}
Hope you can help, drives me nuts.
Regards,
Marc
how is it possible that the method refers to the correct alert view?
For exactly that reason, the delegate method alertView:didDismissWithButtonIndex: actually tells you which alert view it refers to. Note that the method has two arguments. The second one tells you the button index and the first one points to the alert view this button index refers to.
If you have more than one alert view that share the same delegate, you will have to check against the first argument which alert view this is about. To be able to do that, you would have to store the alert views in an ivar/property or other data structure in order to remember them in the delegate method. (Or, since UIAlertView is a subclass of UIView, you could use the tag property to distinguish between multiple views).

show alert xcode and go back after alert

i want to show the alert and when somebody click on OK they need to be send to the page before. How can i make this?
I use the following code:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"BOOYAH!"
message:#"Saved" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
Considering you have 1 option on the alert view and the delegate is self. Use this method in the same .m file as the code above
- (void)alertView:(UIAlertView *)alertV didDismissWithButtonIndex:(NSInteger)buttonIndex
{
//go back a page
[alertV autorelease];
}
Don't forget to release the alert view. I added it in the delegate method, but you can choose to release it right after showing it (only 1 release though)
Assign the UIAlertViewDelegate to self and then implement the following method is called
- (void) alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == buttonIndexForOK) { // Where buttonIndexForOK is the index for your ok button, in this case, that would be zero, but if you want an OK and a Cancel button this would be different.
// go back to the last page
}
}
UIAlertView follows the delegation design pattern that is extremely common in iOS development. You provide a delegate object, and when the object wants to tell you about something, it sends that delegate object a message.
In your code, you've provided self as the delegate. This means that this object needs to conform to the UIAlertViewDelegate protocol.
You will see that there are several methods you can implement to react to various events relating to the alert view. You should use the alertView:clickedButtonAtIndex: method, which provides an index parameter indicating which button was tapped.

UIActionSheet and UIAlertView focus on iPad

I have some troubles with UIActionSheet and UIAlertView on iPad
in fact, i use an alertView as a pop up with textfields and buttons to enter a
date, when i click on the button the UIActionSheet who contains my UIDatePicker is supposed to show, it shows but i don't have focus to pick a date
the focus is still on the alertview and the ActionSheet is in the background
(but on iphone there is no problem it works fine)
is there some code to add for the iPad?
Thanks for your help
In the clickedButtonAtIndex method of your AlertView explicitly dismiss the alertView and show your ActionSheet.
using;
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated and present the action sheet
e.g
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView dismissWithClickedButtonIndex:0 animated:NO];
if(buttonindex==1{
[self showActionSheet]
}
}
NB for Iphone you may not need to dismiss the alertView.