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]
Related
I have a UIButton. I bound a target as follows.
[button addTarget:self action:#selector(myFunction)
forControlEvents:UIControlEventTouchUpInside];
When i click my Button multiple times quickly it invoke the target function multiple times.
On Tapping button i present a new View controller.
when i click 3 times quickly then my new view controller is shown 3 times.
This is something stupid. Whats the point of triggering the function again once the View has been shifted to a new View controller. Why the Hell Apple do such stupid things ?
Any Help please?
First of all its not apple bugs. It should be handle manually. So follow these step
First make your global instance of your button then do this
.h file
#property (weak, nonatomic) IBOutlet UIButton *btn;
.m file
- (IBAction)myFunction:(id)sender
{
self.btn.userInteractionEnabled = NO;
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.btn.userInteractionEnabled = YES;
}
Take one global bool flag like "isItDone" or it declare in singleton class.
in "myFunction" set it as false
which View controller you push on that function in that class's "ViewDidAppear" method set as true.
it will help you.
I have same problem and it is good solution for that to manage it using one global variable.
I think this will help you.
Change your calling function like this
- (IBAction)myFunction:(id)sender
{
UIButton *button = (UIButton*)sender;
button.userInteractionEnabled = NO;
}
and call your function like this
[button addTarget:self action:#selector(myFunction:)
forControlEvents:UIControlEventTouchUpInside];
if you want to store the selection incase you came back to the view controller then only you need to keep a boolean flag to store if its clicked once or not.
Set the IBOutlet to your button, in the viewWillAppear method write,
button.userInteractionEnabled = YES;
and when you click on the button set,
button.userInteractionEnabled = NO;
Is it possible to dismiss the keyboard when you have MULTIPLE UITextFields ? If so how ?
As a side note, do I have to dismiss the keyboard for Each and Every field or can it be done globally ? Oh and it would be super cool if I don't have to touch the DONE button, I'd ideally like a solution that where the user touches anything BUT the field in question and the keyboard automagically disappears...
Oh and if you'd be so kind step by step instructions.
I should have added that I have a method already to resign the keyboard....
However, it only runs when my form is submitted! (see method below)
My question is how to the keyboard to hide/dismiss without having to jump thru so many damned hoops! You'd figure after 6 years, a mature operating system would have a way to GLOBALLY hide the keyboard....NOT!
Ok, enough whining....
- (void)hideKeyboard {
[self.dancePlace resignFirstResponder];
[self.danceGate resignFirstResponder];
[self.danceTerminal resignFirstResponder];
[self.danceText resignFirstResponder];
[self.danceDate resignFirstResponder];
[self.danceStyle resignFirstResponder];
[self.danceTimeOut resignFirstResponder];
}
And this is called when my button is submitted....
- (IBAction)addListingPressed:(id)sender {
// NSLog(#"BUTTON PRESSED");
[self hideKeyboard];
[self valuesAdded];
}
My question, assuming anyone can answer this...and I suspect not, is there a way to globally hide the keyboard if the following conditions are MET: 1.) the user taps OUT of any one of the existing fields, 2.) presses anywhere else on the screen. 3.) Is no more than a line or two in the existing viewcontroller.m file. 4.) I don't have to add a confusing button on the viewcontroller. (any time I have to add outlets, the damned thing is crashing on me...and then nastiness happens, and really...remember I am JUST a beginner, and its very confusing to read that I have to place this here and that there...oy. Simple folks, simple. I'm not looking for elegant solution, just so that it works.
I have a super class that all my view controllers inherit from. In that class I have this code.
MySuperViewController.h
#import <UIKit/UIKit.h>
#interface MySuperViewController : UIViewController
#property(strong, nonatomic) UITapGestureRecognizer *backgroundTapGestureRecognizer;
#end
MySuperViewController.m
- (void)viewDidLoad{
//add a tap gesture recognizer to capture all tap events
//this will include tap events when a user clicks off of a textfield
self.backgroundTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onBackgroundTap:)];
self.backgroundTapGestureRecognizer.numberOfTapsRequired = 1;
self.backgroundTapGestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:self.backgroundTapGestureRecognizer];
}
- (void)onBackgroundTap:(id)sender{
//when the tap gesture recognizer gets an event, it calls endEditing on the view controller's view
//this should dismiss the keyboard
[[self view] endEditing:YES];
}
I have the UITapGestureRecognizer as a public property, so I can override it if I need to.
subclass
MyViewController.h
#import <UIKit/UIKit.h>
#import "MySuperViewController.h"
#interface MyViewController : MySuperViewController<UIGestureRecognizerDelegate>
#end
MyViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//You don't always want the keyboard to be dismissed, so you tie into the gesture recognizer's delegate method
//By doing this, you can stop the endEditing call from being made
[self.backgroundTapGestureRecognizer setDelegate:self];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//touch.view is the view that recieved the touch
//if this view is another textfield or maybe a button, you can return NO and the endEditing call won't be made
if (touch.view == self.myViewThatShouldNotBeBlocked) {
return NO;
}
//if you want the gesture recognizer to accept the event, return yest
return YES;
}
I uploaded an example project to github.
https://github.com/JeffRegan/KeyboardBeGone
RDVKeyboardAvoiding is a scroll view with a tap gesture recognizer, designed for multiple textViews/textFields. It keeps track of the active view and removes a lot of boilerplate code.
tap anywhere outside the textField .. it will hide it..
[self.view endEditing:YES];
There are couple of other ways to do it.
[myEditField resignFirstResponder];
[myEditField endEditing];
[parentView endEditing];
If you dont wont to do so many things and simply want to dismiss keyboard than give iboutlet to each of your text filed to following method..
-(IBAction)hidekeyboard:(id)sender
{
[sender resignFirstResponder];
}
Yes, you only have to dismiss it for the one that is currently being edited.
In order to know which one is being edited, you can check the -(BOOL)isFirstResponder property, which will return YES if it is the first responder (the one being edited) or NO if it is not. Once you know which one is the first responder you can call -(void)resignFirstResponder on that one to get rid of the keyboard.
For example, if you have a method called -(void)aMethod that you want to dismiss the current view controller and you have an array of textViews called textArray, you could do a little loop such as:
-(void)aMethod {
for (UITextField *text in self.textArray) {
if ([text isFirstResponder]) [text resignFirstResponder];
return;
}
}
This way, you can have a variable number of textFields and it will still work.
If you only have one or two textFields and you do not want to create an Array object, you could do (assuming the fields are named text1 and text2:
-(void)aMethod {
if ([text1 isFirstResponder]) [text1 resignFirstResponder];
else if([text2 isFirstResponder]) [text2 resignFirstResponder];
}
Also, to make things easier for the future you could create a category method for UIView (which is what I do) to get the current first responder if it exists as a subview of that view:
#implementation UIView (GetFirstResponder)
- (UIView *)getFirstResponder {
if ([self isFirstResponder]) return self;
else {
for (UIView *subview in self.subviews) {
UIView *firstResponder = [subview getFirstResponder];
if (firstResponder) return firstResponder;
}
}
return nil;
}
You can put this method on the top of any file that you want to call it from, or create a separate file for it and import it.
Once you have this method, you can call:
- (void)aMethod {
UIView *view = [self.view getFirstResponder];
if (view) [view resignFirstResponder];
}
[superview endEditing:YES]; // superview can be the view controller's view property.
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 tried a few things myself, but couldnt really get the handle around it.
I wanna do two things:
First the user can press one of three buttons - They all link to the same ViewController, but when User Presses the first button three labels change accordingly in this second ViewController. And then the user can enter some data which will be displayed in the third view, also accordingly on which button was pressed in the first view.
I tried it with IF Statements, e.g. (IF ViewController.button1waspressed == True) and it didnt really work. I also tried it with tags e.g. (Button1.tag = 1)
Could someone give me a short example on how this could work?
FirstViewController.m
- (IBAction)switch:(id)sender;
{
SecondViewController *second =[[SecondViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
SecondViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
if (sender == self.button1) {
NSString *greeting = [[NSString alloc] initWithFormat:#"Randomtext"];
self.label.text = greeting;
}
}
The problem is obvious in this one, SecondViewController cant see the property from the first one. (And yes I imported the FirstViewController and vice versa)
Your buttons should all directly call IBActions (methods defined like so):
- (IBAction)doSomething:(id)sender;
Defining them as IBActions exposes them to be connected with the blue connection lines in interface builder. Once you've hooked them up and the method is being called, you can simply use an equality check on the sender parameter, which the calling button will automatically set as itself.
if (sender == self.myButton) {
// do something
}
Here I'm assuming that you've got a property called myButton in your ViewController, which would be an IBOutlet:
#property (nonatomic, retain) IBoutlet UIButton *myButton;
This exposes that property to be connected with the blue connection lines in interface builder, so your ViewController will know exactly which button you're talking about when you say myButton.
I've just started with xcode and objective-c and did some very basic apps, but what i'm having problem with is very basic this. the keyboard return button not hiding the keyboard.
I've searched the internet for the solution and all they say is to connect delegate to the file's owner and add the function and it should work, i did that and nothing is working.
I have an ok button and it is working and also clicking on any free space on the screen is working, just the return button....
I am using the simulator, not testing on iphone yet. (xcode 3.2.5 64 bit with the 4.2 simulator).
This is the line of code that should connect the delegate to every textFiled.
1. i've tried already to return both YES and NO, didn't work.
2. i've tried both a specific object name for the textField and this general way, didn't work.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
In the: basic view controller connection -> connections -> outlets, i have the: delegate -- File's Owner. and in the file's owner in referencing outlets there is: delegate - Round style text.....
EDIT - i forgot to mention before, i've check and the method isn't being called!!!
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
what should i do to make it happen? that is why people say to connect the delegate, but in my case it is connected and not triggering the function...i know it is kind of dumb question but for a nobie like me the solution is not obvious...
OK, another Edit - with all my code: just can't understand what to do....
This is: basicViewController.h:
#import <UIKit/UIKit.h>
#interface basicViewController : <#superclass#> <UITextFieldDelegate>
#interface basicViewController : UIViewController <UITextFieldDelegate> {
//every object that we want to interact with (like text field or lable) is call an outlet!!!!
//here we define the outlets for our program
IBOutlet UITextField *txtName;
IBOutlet UILabel *lblMessage;
}
//here are the getters and setter for our outlets
#property (nonatomic, retain) IBOutlet UITextField *txtName;
#property (nonatomic, retain) IBOutlet UILabel *lblMessage;
//method decleration for the OK button action
- (IBAction) doSomething;
//method for hiding the keyboard when clicking on empty area in the app
//we will put an invisible button on all area and clicking on it will make keyboard disapear
- (IBAction) makeKeyboardGoAway;
#end
This is basicViewController.m:
#import "basicViewController.h"
#implementation basicViewController
//synthesizeing the objects that we made' this will create the getter and setters automaticly
#synthesize txtName;
#synthesize lblMessage;
- (IBAction) doSomething{
// makeing keyboard disapear when pressing ok button (doing that form the text field)
//when pressing the OK button, the keyboard will disapear and when clicking in the text field it will show again
[txtName resignFirstResponder];
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %#",txtName.text];
//the objective-c way for setting the test in the text field
[lblMessage setText:msg];
//the regular object oriented way
//lblMessage.text = msg;
[msg release];
}
- (IBAction) makeKeyboardGoAway{
[txtName resignFirstResponder];
}
//when clicking the return button in the keybaord
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Maybe now i am more clear, sorry i didn't do it before.
Any one has an idea what am i doing wrong? it should be pretty strait forward.....
EDIT - Adding an image of all the elements, i hope that will help to help me :-)
10x a lot for every one that is trying to help....i really like this framework, it is so great after c++ and java, python and many other...and i am working with a book, but it is for ios 3.1, maybe that is the problem.....
Firstly you should check if textFieldShouldReturn: is actually being called by adding an NSLog statement or breakpoint at the beginning of the method.
Once that's out of the way, try an manually declare that your view controller conforms to <UITextFieldDelegate> protocol in your interface file:
#interface YourClass : ... <UITextFieldDelegate>
Also declare a property & outlet for your UITextField, make the appropriate connections in IB and manually declare self as the UITextField delegate with:
self.yourUITextFieldObject.delegate = self;
Once that's done see if your method above is now being called and make sure you return YES.
Just write one line in the
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
}
before return YES;
the final version will be as given below:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"%#",textField.text);
}
You need to assign the delegate of the textfields to your file owner. The textfields are sending the message, but doesn't have a delegate to respond to it.
Use the interface builder to do that.
You have to implement this method..
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Like Rog said, don't forget to register the textfield to the delegate, you can do this manually as he said but in Storyboard you can just control drag from all of your textfields to the view controller and register the delegate (choose delegate). Only the textfields that are registered can make use of all those methods.
So this line is important:
self.yourUITextFieldObject.delegate = self;
Or even more easy these days is to just use the storyboard:
textfield is in a subview? in this case, make sure textfield have as delegate the FileOwner.
put a log at the
- (IBAction) makeKeyboardGoAway
function. I think its this method everytime anything is tapped on the screen. In that case, you will need to send the touch event to the text field. Not sure how this is done but that should do it.
Else try removing the which takes care of tap(click) all over the view and try to do what you are doing.
Most likely the problem is that your actual view controller in the running application is not a "basicViewController" but a UIViewController that does not implement the UITextFieldDelegate-protocol.
What you've done in the interface builder by selecting your class "basicViewController" as the FilesOwner is just declaring the FilesOwner-object in your running application to be of type basicViewController; the actual object is not instantiated by this declaration and in your case it is not in the xib / nib.
Some other part of your code actually instantiates a view controller object and loads the xib / nib file. At that place, I guess your code is instantiating a UIViewController (typically by auto-generated code) and not an instance of your basicViewController; you simply have to change the class there.
Furthermore, this error often happens when using a UINavigationController or UITabBarController in the Interface Builder that is (should be) configured to instantiate and load other custom views. If you use such a higher-level controller, double-check that it is actually configured to use your basicViewController, not UIViewController when loading your view from the xib / nib.
Hope, that solves the issue!
Can you try this..
#interface ClassName : SuperClass < UITextFieldDelegate >
Use like this...
textfield.delegate=self;
and use the UITextFieldDelegate in .h class
You can always dismiss the keyboard when you don’t even know which view the text field is in by using:
Objective-C:
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder)
to:nil
from:nil
forEvent:nil];
Swift:
UIApplication.sharedApplication().sendAction("resignFirstResponder",
to:nil,
from:nil,
forEvent:nil)