I am using a uipopover to present a mini number pad to the user when they enter a textfield on my main view controller.
when they enter numbers using the number pad, i save the entry into a nsstring property that I've named keypadvalue.
there is an unwind segue wired to a done button on the popover which fires the following code.
- (IBAction)doneWithKeyboard:(UIStoryboardSegue *)segue
{
NSLog(#"unwind");
if ([segue.sourceViewController isKindOfClass:[KeyPopupViewController class]])
{
KeyPopupViewController *popOver2 = segue.sourceViewController;
activeField.text =popOver2.keypadValue;
}
}
the activetextfield on my main view controller then gets updated to the kepadvalue, and this all works fine.
my problem now is that i want the activetextfield to update the same way if the user presses outside the uipopover, and it dismisses without firing the unwind segue.
i thought i might use the following to perform the update when the popover dismisses
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
activeField.text = controller.keypadValue;
return YES;
}
unfortunately despite multiple attempts i can't get the property to return a value it is always null even though the method fires as expected.
how should i recover the property value from the popover using this or another method?
i am obviously doing something wrong
can anyone advise
thanks
It should help:
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.view endEditing:YES];
activeField.text = controller.keypadValue;
return YES;
}
Related
I have a UITableView that i would like to hide until the user taps the button searchButtonTapped. (I'm also using this button as an IBAction.)
Originally i'm hiding the table view as you see in the viewDidLoad, and i wanna show it after the button was tapped, but it does not shown up after i tap the search button. Do i missed something? For me, it seems it should be work properly, after the button was tapped i refresh the table view.
my .h file
#property (weak, nonatomic) IBOutlet UIButton *searchButtonTapped;
- (IBAction)searchButton:(id)sender;
.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.hidden = YES;
}
- (void)buttonTapped:(id)sender {
if (sender == self.searchButtonTapped) {
self.tableView.hidden = NO;
[self.tableView reloadData];
}
}
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
It's impossible to tell from the little bit of code that you posted. Add NSLog statements in your buttonTapped method that show entering the method, entering the if statement, the value of searchButtonTapped, and the value of self.tableView.
Then you can tell if the method is getting called, if the if statement is evaluating as true, and if the table view is non-nil. One of those things is likely to be the cause of your problem.
I'm guessing that the if statement is wrong. what type is the property self.searchButtonTapped? Post the code that declares that property.
Based on the name I would guess that searchButtonTapped is a boolean?
you have declared only one IBAction, which is for the method searchButton.
This method call the searchSetup´s method. What is the purpose of it?
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
So you must have another IBAction for buttonTapped method witch is currently a "void" method and not a IBAction. Or you make that connection from the storyBoard, or you must declare it programaticly like:
[self.searchButtonTapped addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]
I'd like to achieve the following behaviour of a single UITextField and the keyboard:
when the view has loaded UITextField becomes first responder and the keyboard opens (so far so good):
- (void)viewDidLoad
{
[self.editField becomeFirstResponder];
self.editField.delegate = self;
}
Now user inputs some text and presses the return key. That text is added to the data source in the following method:
- (IBAction)didEndOnExit:(id)sender {
//add self.editField.text to data source
}
Now after the return key is pressed and the above UITextField's method gets called and executed I would like the UITextField to clear, the cursor to be placed and be visible at the beginning of the text field and the keyboard not to hide so that new item could be entered in the textfield and added to the data source.
This is how I return to the previous view in the app (using a button):
- (IBAction)backButtonPressed:(id)sender {
[self dismissViewControllerAnimated:NO completion:^{}];
}
I tried playing with UITextFieldDelegate's methods and UITextField's becomeFirstResponder and resign FirstResponder, but am unable to achieve the above described behaviour. I've seen posts here on Stack Overflow about using consecutive UITextField's to enter data, but not to use the same UITextField time and again.
You should override the below mentioned method and do whatever you want and showing the keyboard too.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
Have a try :)
While dismissing view controller all other code executions freezes when (view controller is being dismissed).
Use some delay (performselectorafterdelay). or
completionhandler of dismissingviewcontroller for executing your code when viewcontroller is being dismissing and
Also execute code on main Thread which includes UI changes or updates
after saved your data.. you have to make the uitextfield to be nil... like self.editField.text = nil. then you can call [self.editfield becomesfirstresponder].. after you will add more items to array or else anything everytime the field should be nil after you added..
From the Doc
Return Value: YES if the text field should implement its default
behavior for the return button; otherwise, NO.
For EX - Use the Delegate of UITextField :
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
//add self.editField.text to data source
textField.text = #"";
return NO; // This will do your need
}
Because I used UITextField's action method - (IBAction)didEndOnExit:(id)sender the keyboard always got closed. Apparently that method makes the UITextField resign from being first responder. Instead of adding data to data source in that method, it can be added in the delegates's method - (BOOL)textFieldShouldReturn:(UITextField *)textField and so the keyboard won't close.
I have an app with tabbed view: search | subscribes | messages
All tab buttons are visible at app start even for unauthorized user.
But when unauthorized user clicks on let's say messages tab, I want to show "MessagesViewController" but it must show grey screen:
Please sign-in. [button sign-in] [button registration]
When user clicks [button sign-in] - modal UIViewController appears. After sign-in user goes back to "MessagesViewController" tab, but this time user can see his messages. Same grey screen must be in subscribes tab.
I'm new to iOS so I want to know what is a proper way to do this. Subscribes and messages are table views. Do I need to place another view on top of tables to overlap them and then hide it after authorization? Or can I create one separate "unauthorized" controller, connect it with tabs and reuse it? If so, how can I connect messages and subscribes controllers back to tabs after sign in?
Create a baseViewController, make all three viewController's extend that base.
Think of a method that will show the user "please sign-in" message. A gray UIView (with a UILabel and two UIButtons) overriding all the content seems good to me.
Add the buttons on that gray UIView, with self s as targets
Check in the viewWillAppear method whether the user is not logged in or not. Show the gray view if not.
Create a boolean and before you fire the segue you proof, if the boolean is yes or no. When the boolean is yes, the segue is performed. Otherwise a segue to your Login View is performed.
I hope this solves your problem
you can use
- (void) viewWillAppear:(BOOL)animated
to do this
#interface Messages
{
BOOL loggedIn;
UILabel *pleaseSignIn;
UIButton *signin;
UIButton *register;
}
- (void) viewWillAppear:(BOOL)animated
{
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"logged"] isEqualToString:#"YES"])
{
loggedIn = YES;
}
else
{
loggedIn = NO;
}
if(loggedIn)
{
//Display messages
pleaseSignin.hidden = YES;
signin.hidden = YES;
register.hidden = YES;
}
else
{
//Remove messages view
pleaseSignin.hidden = NO;
signin.hidden = NO;
register.hidden = NO;
}
}
I'm trying to get rid of the keyboard when the user touch outside my UITextField, by using this method:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[mainTextController resignFirstResponder];
[super touchesBegan:touches withEvent:event];
}
However, this seems to call a method that is called after pressing the return button on the keyboard, but I just want the keyboard to vanish, not to press return for me.
How can I accomplish that?
Thanks!
EDIT: tGilani's answer is the most straight-forward way, works like a charm, without changing to UIControl. But I guess jonkroll's answer also works.
try
[self.view endEditing:YES];
Update:
Take a boolean value and set it to false in init method. In your textFieldShouldReturn delegate method method, execute the code if it is false, skip otherwise
- (BOOL) textFieldShouldReturn:(UITextField*)textField
{
if (!boolean)
{
// YOur code logic here
}
boolean = false;
}
in your method where you call the endEditing method, set boolean to true.
boolean = YES;
[self.view endEditing:YES];
Here's how I've handled this before. First create a method on your view controller that will dismiss the keyboard by resigning first responder status on your text field:
- (IBAction)dismissKeyboard:(id)sender
{
[mainTextController resignFirstResponder];
}
Next, in your storyboard scene for your ViewController (or nib, if you are not using storyboards) change the class of your ViewController's view property from UIView to UIControl. The view property is effectively the background behind your other UI elements. The class type needs to be changed because UIView cannot respond to touch events, but UIControl (which is a direct subclass of UIView) can respond to them.
Finally, in your ViewController's viewDidLoad: method, tell your view controller to execute your dismissKeyboard method when the view receives a UIControlEventTouchDown event.
- (void)viewDidLoad
{
[super viewDidLoad];
UIControl *viewControl = (UIControl*)self.view;
[viewControl addTarget:self action:#selector(dismissKeyboard:) forControlEvents:UIControlEventTouchDown];
}
EDIT:
Part of your concern seems to be that textFieldDidEndEditing: is called when the keyboard is dismissed. That is unavoidable, it will always be called whenever a text field loses focus (i.e. first responder status). It sounds like your problem is that you have put code to perform when the user clicks the return button in textFieldDidEndEditing:. If you do not want that code to run when the user touches outside of the text field, that is not the proper place to put it.
Instead, I would put that code in a separate method:
- (IBAction)textFieldReturn:(id)sender
{
if ([mainTextController isFirstResponder]) {
[mainTextController resignFirstResponder];
// put code to run after return key pressed here...
}
}
}
and then call that method via Target-Action when your text field sends the control event UIControlEventEditingDidEndOnExit.
[mainTextController addTarget:self action:#selector(textFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
Note that UIControlEventEditingDidEndOnExit is different than UIControlEventEditingDidEnd. The former is called when editing ends by the user touching outside the control, the latter is called when editing ends by the user pressing the return key.
You need to change your ViewController's view property from UIView to UIControl using the Identity Inspector:
From there, you simply create an IBAction and tell the textfield to dismiss (which I am assuming is your mainTextController). If mainTextController is not the textfield you want the keyboard to dismiss on then change the resignFirstReaponder method to your textfield like so.
- (IBAction)backgroundTap:(id)sender {
[myTextField resignFirstResponder];
}
then from there go back into your View Contoller's .xib file and connect the action to the Control View and select "Touch Down".
I am running into an issue where the keyboard does not get dismissed when leaving a UITextField or UITextView in a UIModalPresentationFormSheet. In addition, I've created a large button to serve as the view's background so if the user taps outside the fields it gets triggered. I am using the same code in a regular view controller, and it works as expected. In the modal view controller it does nothing. Any suggestions would be appreciated.
- (BOOL)textFieldShouldReturn:(id)sender {
[titleTextField resignFirstResponder];
return YES;
}
- (BOOL)textViewShouldReturn:(id)sender {
[synopsisTextView resignFirstResponder];
return YES;
}
- (IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)textViewDoneEditing:(id)sender {
[sender resignFirstResponder];
}
- (IBAction)backgroundClick:(id)sender {
[titleTextField resignFirstResponder];
[synopsisTextView resignFirstResponder];
}
Overriding disablesAutomaticKeyboardDismissal to return NO as below fixed the same problem of mine. You should put this code to your view controller, from which you initiate the keyboard:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
Also, check this SO question if you want to get a detailed explanation.
For those having trouble with UINavigationController, I think there is a better solution than a category on UIViewController. We should change the behavior of UINavigationController to ask its topViewController (in my opinion, this is how all ViewController containers should handle this).
#implementation UINavigationController (DelegateAutomaticDismissKeyboard)
- (BOOL)disablesAutomaticKeyboardDismissal {
return [self.topViewController disablesAutomaticKeyboardDismissal];
}
If you're presenting a modal view with presentation style "form sheet", Apple apparently does not dismiss the keyboard, thinking that they don't want the keyboard to jump in and out where a user will be doing a lot of editing (i.e. "forms"). The fix would be to change presentation style or live with it.
If you implement the UITextFieldDelegate protocol you can inadvertently cause this behavior if you do text validation. If your validation codes returns false from textFieldShouldEndEditing when the text is invalid, the field can't relinquish it's firstResponder status and the keyboard will remain on screen in the next view.
More details at UITextField's keyboard won't dismiss. No, really
I solved this by resizing a UIModalPresentationPageSheet. See my answer here.
The disablesAutomaticKeyboardDismissal refused to work for me on iOS 7.
But... I managed to solve this issue by simply disabling the UITextFields on the screen.
My solution is described here.
This workaround even works on Modal UIViewControllers.
Yeah... it surprised me aswell !!
i have also facing same problem and also done everything but not thing works then i start thinking and get some result.
but this answer for those who want to dismiss keyboard on textfield click and then open pop up.
so all you need to call text field delegate
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == self.myTxtFieldName{
self.view.endEditing(true) // keyboard hide code
// here you can call your model or pop up code and keyboard will dismiss and your pop up open
return false
}
return true
}
Sorry if this is not working for you
if there is other answer then please edit it
Thank you