Prevent AlertView dismissal - objective-c

Can anyone help me in preventing dismissal of alertview on its button click event??
I have a textview as a subview of my alertView and i dont want to dismiss it if textview's value is nil.

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;
}
}
Alternately, there is a much faster approach:
return [inputText length] ? YES : NO;
The does the same thing as the if statement does.

That might be against HIG Guidelines to NOT to dismiss an UIAlertView.
WORKAROUND : I don't know what goes on in your app, but to acheive this thing, what you could do is dismiss the AlertView and then check if textView's text is set or not. If it is set to nil, then bring up the alertview again!

i'm not sure you can.
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
is the only option available on callBack. And there's still at least one active button.
If you really need that specific behavior, try reimplementing your own UIAlertView

Related

Dont show keyboard when textfield is tapped

I have a UITextField and a UIDatePicker in my XIB file, now I assigned the date that is chosen on the UIDatePicker to be the value of the text in my textfield. I've done this well, my only problem now is that I want the keyboard not to show when I tap on the textfield.
I'm sure somebody knows the answer, I will be glad if you will share it :) Thanks!
btw. I tried this, but it didn't work..
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
Just set the UIDatePicker as the inputView of your UITextField.
This wil repalce the keyboard as the input view when the user clicks on the UItextField with the UIDatePicker.
self.dateTextField.inputView = self.datePicker;
You can set delegate in your UITextField and return NO in textFieldShouldBeginEditing.
Try this:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField.tag == YOU_TEXT_FIELD_TAG) {
return NO;
}
return YES;
}
Don't forget to make yourViewController conform to <UITextFieldDelegate> and also set yourTextField.delegate = self;
Since I didn't saw full answer, that I also needed, and come to solution with some answers here I'll put my code.
Simply put some "blank" UIView as input view.
Objective C
UIView *hideKeyboardView = [[UIView alloc]init];
self.yourTextField.inputView = hideKeyboardView;
Swift
let hideKeyboardView = UIView()
yourTextField.inputView = hideKeyboardView
I already fixed it! I added the following code on the viewDidLoad
[self.dateField addTarget:self action:#selector(textFieldDidBeginEditing:)
forControlEvents:UIControlEventEditingDidBegin];
and I still used
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
Thanks for all your help anyway! Hope this thread will help others..

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.

resignFirstResponder not hiding UIkeyboard in iPad

I have an iPad application in which resignFirstResponder does't seems to be working.
I have tried many solutions. I am just calling resign first responder from the instance of the firstResponder object but keyboard is remain there on the screen. THen I tried by iterating all the window to get the instance of the first responder and then I am calling the resignFirstResponder from that instance.
I also try by creating the category of the UIViewController for the following methods.
- (BOOL)disablesAutomaticKeyboardDismissal
{
return NO;
}
But this solution is also not working for me. And this keyboard problem is there in all the textfield of application not only for some specific textfield.
Update:
In different part of the app I am using different code for this purpose. Here is the code
- (void)textFieldDidEndEditing:(UITextField *)mtextField
{
[mtextField resignFirstResponder]; this one is not required but I have just write it here.
}
- (BOOL)textField:(UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([string hasSuffix:#"\n"])
{
[theTextField resignFirstResponder];
return NO;
}
return YES;
}
Update: When I try by running the application in the simulator, some times it resignFirstResponder is working, but not on every launch even in simulator.
the simplest and best way to hide the keyboard is to use
[self.view endEditing:YES];
and make sure you are setting appropriate delegate of the textfields
If you want the keyboard to resign when you press the return key, you need to use:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Then the textFieldDidEndEditing gets invoked.
I got the solution for this problem. Actually there seems to some change in the apple cocoa API. In my app I have an UIAlertView, which we used to display to show that some operation is going on and user should wait to finish it. For that purpose the code I use in my app was
- (void)displayAlertView
{
UIAlertView *alertView = creating the object;
UIActivityIndicatorView *activityIndicator= creating the object;
[alertView addSubview:activityIndicator];
[activityIndicator startAnimating];
[alertView show];
[alertView release];
}
-(void)didPresentAlertView:(UIAlertView *)alertView
{
[alertView dismissWithClickedButtonIndex:0 animated:NO];
}
The problem get resolved when I use the code below in my application
-(void)didPresentAlertView:(UIAlertView *)alertView
{
[self performSelector:#selector(dismissView:) withObject:alertView afterDelay:0.0];
}
-(void)dismissView:(UIAlertView*)alertView
{
[alertView dismissWithClickedButtonIndex:0 animated:NO];
}
I think here some thing is going wrong in the UIAlertView, and because of that keyboard is not hiding when resigning as the first responder.
First of all, you don't call methods in Objective-C, rather you send messages to objects.
UIView isn't the one who should send the message resignFirstResponder. Have your UITextField as a property - let's call it myTextField. You should use this:
[self.myTextField resignFirstResponder];

UISearchBar select all text

Is there any way to select all text in UISearchBar?
I tried [searchBar selectALL:], but it throw the signal (unrecognized selector).
I want to allow user to alter previous search text. At the some time, when user just starts typing new request, the old one should be dismissed. The standard way how to achieve it - select all text at the moment when text begin editing.
This can be accomplished using the standard UIResponder semantics. No need to dig down into the private view hierarchy of UISearchBar.
[[UIApplication sharedApplication] sendAction:#selector(selectAll:) to:nil from:nil forEvent:nil]
You can call this from anywhere, and the selectAll: selector will run the responder chain to see if any objects respond to it. Assuming your search bar is currently the first responder (if the user is typing in it), it will respond and the result will be all text selected. If not you can make it the first responder by calling becomeFirstResponder on the search bar.
[_mySearchBar becomeFirstResponder]
[[UIApplication sharedApplication] sendAction:#selector(selectAll:) to:nil from:nil forEvent:nil]
If you want the 'type to replace' functionality that selecting the text in the UITextField gives you (ie the extra tap on the cross is unacceptable), you can dig through the subviews of the UISearchBar to find the UITextField (or UISearchBarTextField) and select its text:
// need to select the searchBar text ...
UITextField * searchText = nil;
for (UIView *subview in searchBar.subviews)
{
// we can't check if it is a UITextField because it is a UISearchBarTextField.
// Instead we check if the view conforms to UITextInput protocol. This finds
// the view we are after.
if ([subview conformsToProtocol:#protocol(UITextInput)])
{
searchText = (UITextField*)subview;
break;
}
}
if (searchText != nil)
[searchText selectAll:self];
In my case, the sending selectAll(_:) didn't work immediately after calling becomeFirstResponder.
I worked around it by waiting one runloop:
Swift 2:
dispatch_async(dispatch_get_main_queue()) {
UIApplication.sharedApplication().sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, forEvent: nil)
}
Swift 3:
DispatchQueue.main.async(execute: {
UIApplication.sharedApplication().sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, forEvent: nil)
})
Here is another suggestion: when someone activates the search bar, there are two possible intentions: type new text or add to the existing text. I think you should give your user the choice.
If he wants to add text he naturally taps again at the end of the existing text.
If he wants to start over, he can press the clear button that automatically appears when the search bar becomes active.
Swift 4
If you want to select all text when searchBar become first responder.
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
DispatchQueue.main.async {
UIApplication.shared.sendAction(#selector(UITextField.selectAll(_:)), to: nil, from: nil, for: nil)
}
return true
}
I dont think there is a method to select all text. Maybe when there is a focus on UISearchBar you can clear the search bar like so - searchBar.text = #""
i.e. clear text in the search bar... Hope this helps in some way...
You can accomplish this by keeping a BOOL indicating if editing the search bar text field just started. Then, you can catch the first key press in the searchBar delegate methods.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
firstEdit = YES;
}
- (BOOL)searchBar:(UISearchBar *)searchBar
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text {
if (firstEdit) {
searchBar.text = text;
firstEdit = NO;
}
return YES;
}

prevent UIAlertView from dismissing

As a form of validation, is there any way to prevent an alert view from dismissing when pressing an "OK" button?
Scenario: I have 2 text fields in the alertview for username/password. If both are empty and the user presses "OK", I do not want the alert to be dismissed.
iOS 5 introduces a new property to UIAlertView to handle exactly this problem.
alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
Apple documentation on UIAlertView.
Add the new UIAlertViewDelegate method to handle the enabling/disabling of the button.
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
Apple documentation on UIAlertViewDelegate.
You’re doing it the wrong way, you should enable and disable the submit button according to the input. First you have to get access to the button. This is easy, just create the alert without buttons, create a standalone button and add it to the dialog:
[alert addButtonWithTitle:#"OK"];
UIButton *submitButton = [[alert subviews] lastObject];
[submitButton setEnabled:…];
And then you have to set a delegate for those textfields and enable or disable the button when the fields change:
- (BOOL) textField: (UITextField*) textField
shouldChangeCharactersInRange: (NSRange) range
replacementString: (NSString*) string
{
int textLength = [textField.text length];
int replacementLength = [string length];
BOOL hasCharacters = (replacementLength > 0) || (textLength > 1);
[self setButtonsAreEnabled:hasCharacters];
}
// Disable the ‘Return’ key on keyboard.
- (BOOL) textFieldShouldReturn: (UITextField*) textField
{
return NO;
}
Of course you should wrap all this into a separate class so that you don’t mess up your calling code.
I don't believe you actually need to pass in any button names. Just take out your OK button string and leave it as "nil".