#implementation
UIAlertView *query;
#end
- (void)viewWillAppear:(BOOL)animated {
query = [[UIAlertView alloc]
initWithTitle:NSLocalizedString(#"New", #"")
message:nil
delegate:self
cancelButtonTitle:NSLocalizedString(#"Cancel", nil)
otherButtonTitles:NSLocalizedString(#"OK", #""), nil];
query.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField *textField = [_query textFieldAtIndex:0];
textField.placeholder = NSLocalizedString(#"Title", #"placeholder text where user enters name for new playlist");
textField.delegate = self;
[_query show];
}
After UIAlertView is shown, keyboard is shown too and UITextfield is focus (It just works on pre iOS7, but does not work in iOS8). I have tried [textfield becomeFirstResponder], but it does not worked. I create new project and use cove above, it works.
My problem: Keyboard does not shown with UIAlertViewStylePlainTextInput style.
I don't know why? Can anybody helps me?
Thanks.
Here's a slight improvement to Chen Lim's hack/fix, to be placed in the UIAlertViewDelegate:
- (void)didPresentAlertView:(UIAlertView *)alertView {
if (isIOS8) {
// hack alert: fix bug in iOS 8 that prevents text field from appearing
UITextRange *textRange = [[alertView textFieldAtIndex:0] selectedTextRange];
[[alertView textFieldAtIndex:0] selectAll:nil];
[[alertView textFieldAtIndex:0] setSelectedTextRange:textRange];
}
}
(You'll have to implement an isIOS8 method, property, or iVar.)
This ugly hack worked for me, after calling show:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// HACKHACK: This is to make the keyboard appear in iOS8
UITextRange* textRange = self.textField.selectedTextRange;
[self.textField selectAll:self];
[UIMenuController sharedMenuController].menuVisible = NO;
self.textField.selectedTextRange = textRange;
});
Ran into the same problem, and spent hours fiddling with UIAlertController, which is the "right" solution, but unfortunately has several issues elsewhere (e.g. it breaks when presenting from a popover), and won't work with iOS7.
This is definitely a bug in iOS8. I hope Apple fixes this soon. It unfortunately breaks even with older binaries compiled for iOS7.
This helps me to fix all related issues:
[MyUITextView endEditing:YES];
Put it before showing UIAlertView.
In my case this was happening because the UIViewController that was presenting the UIAlertView had implemented canBecomeFirstResponder with a YES result since I wanted to listen for 'shake' events.
Once I added the following implementation of the UIAlertViewDelegate method the keyboard was presented as expected:
- (void)willPresentAlertView:(UIAlertView *)alertView
{
[self resignFirstResponder];
}
So this may not solve all of the problems with this so-called 'deprecated' class but it is something to check if your controller is enabling first-responder behaviour.
For me the issue was that a text field already had first responder status, so the keyboard was already visible when the alert code was invoked. Dismissing this field fixed the issue.
Are you seeing this on a device, or just in the sim?
There appears to be an issue with the iOS8 sim where it detects a physical keyboard, and doesn't show the software keyboard. Could possibly be intentional, as you technically are using a physical keyboard...it's just not the ideal behavior for sim testing.
Try command K to toggle the software keyboard in the sim if that's your issue.
I came cross with the same situation,and how I solved this bug is trying to resign current responder before showing the alertView.And UITextField's keyboard is popping up as expected.
UITextField *textField = ...; // Suppose textField is currently being edited.
[textField resignFirstResponder]; // before showing,resign first.
[_query show];
The first page of the UIAlertView documentation states:
Subclassing Notes
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this
class is private and must not be modified.
For more information about appearance and behavior configuration, see
“Alert Views”.
In other words, you shouldn't be messing around with the contents of UIAlertView window. The fact it actually works in earlier OS versions than iOS 8 is just a bonus. It's deprecated as of iOS 8.
What you'll want to do in iOS 8 is make use of the brand new UIAlertController class, which does allow editable text fields.
Related
I have an application that uses UIAlertView in its login Window normally:
self.customAlert = [[IFCustomAlertView alloc] initWithTitle:#"Save Password"
message:#"¿Do you want the app to remember your password?"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:#"Cancel", nil];
The problem is... Since I updated my devices to iOS8 whenever this alertView comes up it shows the keyboard and I can't dismiss it. On iOS7 this doesn't happen.
I am resigning the responders of user and password when the send button is tapped:
-(IBAction)btnSendTapped:(id)sender{
[self.tfpass resignFirstResponder];
[self.tfuser resignFirstResponder];
}
I have tried:
[self.view endEditing:YES];
and in some alertViews it does work but in others it doesn't. My AlertViews never have text fields so I think there's no reason for this keyboard to appear.
Also the intro button on the keyboard doesn't hide it, so sometimes the OK and Cancel buttons are obstructed by the keyboard and I can't do nothing on the screen.
I think this may have something to to with the UIAlertView deprecation, but I don't know.
I also have these methods implemented:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return true;
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField{
return YES;
}
Any help would be appreciated.
I borrow solution from this blog
For me the keyboard always show up when the alertView.show() has been called.
My solution is using the didPresentALertView method for make sure this will called after the alert view popup. Then we can loop through all UIWindows and it's subviews. I detect it by description name (You can use more accurate method if you want) and just simply remove it from superview.
func didPresentAlertView(alertView: UIAlertView) {
var tempWindow: UIWindow;
var keyboard: UIView;
for var c = 0; c < UIApplication.sharedApplication().windows.count; c++ {
tempWindow = UIApplication.sharedApplication().windows[c] as! UIWindow
for var i = 0; i < tempWindow.subviews.count; i++ {
keyboard = tempWindow.subviews[i] as! UIView
println(keyboard.description)
if keyboard.description.hasPrefix("<UIInputSetContainerView") {
keyboard.removeFromSuperview()
}
}
}
}
Hope this thelp.
I am using a UIAlertView to prompt users for a password. If the password is correct, I'd like the alert view to go away normally; if the password is incorrect, I'd like the alert view to remain (with the text changed to something like "Please try again."). How do I alter the default behaviour so that the view doesn't go away when a button is pressed?
I've tried the subclassing method suggested at Is it possible to NOT dismiss a UIAlertView, but the dismissWithClickedButtonIndex wasn't being called in my subclass. After reading the documentation I see that subclassing UIAlertView isn't supported, so I'd like to try another approach.
If this isn't possible with UIAlertView, is the best option to simply make a password view from scratch? Thanks for reading.
As this is very old question,but I got one solution and though of posting if any other developer need in near future.
Implement protocol methods in .h file
In order to respond to button taps in our UIAlertView, we will use the – alertView:clickedButtonAtIndex: protocol method as
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
}
//Now below code will check if uitextfield value.
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if( [inputText length] > 0)
{
//text field value is greater than zero ,then Done button will appear as blue,or else it will be blurred
return YES;
}
else
{
return NO;
}
}
You could design a UIView similar to the alertview and can cal the functions inside this. Removing a UIView is controlled by you.
It's not possible to leave the alert there when a button has been clicked.
You can either disable the "OK" button by delegate method alertViewShouldEnableFirstOtherButton:, if you are checking the password locally, or just show another alert later. The second alert can contain a different information, e.g. "Password incorrect" instead of "Enter password".
I have a UIAlertView with multiple buttons. Is it possible to grey out and disable a button? I want the button to be visible but clear that it can't be pushed. Any suggestions are appreciated.
Make sure that you have enabled the current VC as implementing the <UIAlertViewDelegate> protocol, and then in your VC you could do the following:
- (void)viewDidAppear:(BOOL)animated {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert!" message:#"This is an alert view" delegate:nil cancelButtonTitle:#"Cancel!" otherButtonTitles:#"Off", #"On", nil];
alert.delegate = self;
[alert show];
}
/* UIAlertViewDelegate methods */
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView {
return NO;
}
// Other UIAlertViewDelegate methods...
Now why you would want to show a UIAlertView with a button which didn't have any functionality is a whole different question... :)
I hear of lots of people subclassing UIAlertView, but then I read this comment on Apple's UIAlertView Class Reference page:
Subclassing Notes
The UIAlertView class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.
i.e. people should not be attempting to modify the elements or behavior of UIAlertView. It's likely that behavior can change in later versions of iOS (e.g. iOS 8 or iOS 7.1 or whatever), breaking their various modifications to UIAlertView.
Anyways, to answer your question: why not try creating your own UIView that you can add as UIAlertView-like subview on top of any of your views? That way, you'd have easy control over both the buttons and their behavior.
I'm a bit new to iOS development, and right now am working on some simple UI-related stuff. I have a UIAlertView that I'm using at one point to allow the user to enter some text, with simple Cancel and OK buttons. The OK button should be disabled if the text field is blank.
I added to my UIAlertViewDelegate an alertViewShouldEnableFirstOtherButton function, so the OK button would disable when there's no text, and I also set the UIAlertView's UITextField to have clearOnBeginEditing true, so the previous text would be gone every time I displayed the alert. Each of these things works perfectly on their own. Unfortunately, it seems like the AlertView is checking whether or not to enable the OK button before the text field is cleared, so when they're put together it comes up enabled. Below should be about the minimal code needed to reproduce.
-(void)viewDidLoad
{
textEntryBox = [[UIAlertView alloc] initWithTitle:#"Name" message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
[textEntryBox setAlertViewStyle:UIAlertViewStylePlainTextInput];
[textEntryBox textFieldAtIndex:0].clearsOnBeginEditing = YES;
}
-(IBAction)functionTriggeredByOtherLogic
{
[textEntryBox show];
}
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
if(alertView == textEntryBox)
{
if([[alertView textFieldAtIndex:0].text length] > 0)
{
return YES;
}
else
{
return NO;
}
}
return YES;
}
So, ultimately, my question is this: am I doing something completely against the natural iOS way of doing things here? Is there a better way to do this? Should I just ignore the clearsOnBeginEditing property of the UITextField, and manually clear the Text property before showing the UIAlertView?
Try to set the textfield delegate to self
[[textEntryBox textFieldAtIndex:0] setDelegate:self]
and implement this method :
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[textField setText:#""];
}
I'm also having a UIAlertView with a textField to fill-in in my app, and it works for me
Using an alert view for this is probably a bit much. It might be easier if you use the master-detail paradigm and just push a new view controller where you can enter your values.
Ours is a health care app. We have a HIPAA-compliant speech recognizer in the app through which all the dictation can take place. The hospitals don't want physicians to accidentally start speaking to the Nuance Dragon server which is not HIPAA-compliant. So, I was looking for ways I could supress the dictation key on the keyboard.
I tried putting a fake button on the Dictation button on the key pad, but on the iPad the split dock concept keeps moving the microphone all over the screen. This does not sound like a reasonable solution. Are there any experts out there who could help me?
OKAY, finally got it! The trick is to observe UITextInputMode change notifications, and then to gather the identifier of the changed mode (Code seems to avoid the direct use of Private API, though seems to require a little knowledge of private API in general), and when the mode changes to dictation, resignFirstResponder (which will cancel the voice dictation). YAY! Here is some code:
Somewhere in your app delegate (at least that's where I put it)
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(inputModeDidChange:) name:#"UITextInputCurrentInputModeDidChangeNotification"
object:nil];
And then you can
UIView *resignFirstResponder(UIView *theView)
{
if([theView isFirstResponder])
{
[theView resignFirstResponder];
return theView;
}
for(UIView *subview in theView.subviews)
{
UIView *result = resignFirstResponder(subview);
if(result) return result;
}
return nil;
}
- (void)inputModeDidChange:(NSNotification *)notification
{
// Allows us to block dictation
UITextInputMode *inputMode = [UITextInputMode currentInputMode];
NSString *modeIdentifier = [inputMode respondsToSelector:#selector(identifier)] ? (NSString *)[inputMode performSelector:#selector(identifier)] : nil;
if([modeIdentifier isEqualToString:#"dictation"])
{
[UIView setAnimationsEnabled:NO];
UIView *resigned = resignFirstResponder(window);
[resigned becomeFirstResponder];
[UIView setAnimationsEnabled:YES];
UIAlertView *denyAlert = [[[UIAlertView alloc] initWithTitle:#"Denied" message:nil delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil] autorelease];
[denyAlert show];
}
}
you can create your own keyboard and set the inputView for the text fields that will accept this dictation. then when they press any keys they will get your keyboard, therefore you dont have to override the keys on the standard keyboard, you will be able to customize the entire thing.
self.myButton.inputView = self.customKeyboardView;
here is an example of an extremely custom keyboard
http://blog.carbonfive.com/2012/03/12/customizing-the-ios-keyboard/
Ray also has a teriffic tutorial on custom keyboards.
http://www.raywenderlich.com/1063/ipad-for-iphone-developers-101-custom-input-view-tutorial
I hope that helps.
I had the same issue and the only way i found that hides the dictation button is changing the keyboard type.
For me changing it to email type seemed to be reasonable:
textField.keyboardType = UIKeyboardTypeEmailAddress;
You could make a subclass of UITextField/UITextView that overrides insertDictationResult: to not insert anything.
This won't prevent the information being sent, but you could then display an alert informing them of the breech.
This is a Swift 4 solution based on #BadPirate's hack. It will trigger the initial bell sound stating that dictation started, but the dictation layout will never appear on the keyboard.
This will not hide the dictation button from your keyboard: for that the only option seems to be to use an email layout with UIKeyboardType.emailAddress.
In viewDidLoad of the view controller owning the UITextField for which you want to disable dictation:
// Track if the keyboard mode changed to discard dictation
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardModeChanged),
name: UITextInputMode.currentInputModeDidChangeNotification,
object: nil)
Then the custom callback:
#objc func keyboardModeChanged(notification: Notification) {
// Could use `Selector("identifier")` instead for idSelector but
// it would trigger a warning advising to use #selector instead
let idSelector = #selector(getter: UILayoutGuide.identifier)
// Check if the text input mode is dictation
guard
let textField = yourTextField as? UITextField
let mode = textField.textInputMode,
mode.responds(to: idSelector),
let id = mode.perform(idSelector)?.takeUnretainedValue() as? String,
id.contains("dictation") else {
return
}
// If the keyboard is in dictation mode, hide
// then show the keyboard without animations
// to display the initial generic keyboard
UIView.setAnimationsEnabled(false)
textField.resignFirstResponder()
textField.becomeFirstResponder()
UIView.setAnimationsEnabled(true)
// Do additional update here to inform your
// user that dictation is disabled
}