Replacing UITextField input with a UIDatePicker - ios

I have a table view controller with (among others) a cell that is to represent a date. I followed this post "How do I make a modal date picker that only covers half the screen?" and I have it working with one big exception - I can't get the picker to disappear!
I tried registering for the event UIControlEventTouchUpOutside, but it seems that this is not generated by the picker (or at least in the mode that I am using it).
How can I recognize that the user has finished selecting a date?
Also, is there a way to disable the user from inputting directly into the UITextField? I want to force them to use the picker. I saw this post "Disable blinking cursor in UITextField?", but is there another way?
Reagards,
--John

Try this code.. here I am putting an datepicker to a uitextfield.. it will have a done button at the top right navigation bar.. so by clicking done I will user can dismiss the datepicker.. the another best method is by putting a toolbar above the datepicker having the done button.. Try this it will work.. when changing the datepicker you can populate the text field.. Hope this helps..
see this stackoverflow link https://stackoverflow.com/a/4824319/763747 this will have the datepicker with done button as toolbar above the keybord..
#pragma mark -
#pragma mark - TextField Delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return TRUE;
}
- (void) textFieldDidBeginEditing:(UITextField *)textField {
itsRightBarButton.title = #"Done";
itsRightBarButton.style = UIBarButtonItemStyleDone;
itsRightBarButton.target = self;
itsRightBarButton.action = #selector(doneAction:);
if ([textField isEqual:itsIncidentDateTextField])
{
itsDatePicker = [[[UIDatePicker alloc] init] autorelease];
itsDatePicker.datePickerMode = UIDatePickerModeDate;
[itsDatePicker addTarget:self action:#selector(incidentDateValueChanged:) forControlEvents:UIControlEventValueChanged];
//datePicker.tag = indexPath.row;
textField.inputView = itsDatePicker;
}
}
- (IBAction) incidentDateValueChanged:(id)sender{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMM d, yyyy"];
itsIncidentDateTextField.text = [dateFormatter stringFromDate:[itsDatePicker date]];
[dateFormatter release];
}

I used a different method for disappearing the UIDatePicker.
create a XIB (nib) file and add to it a UIDatePicker then resize the view so it fits only the UIDatePicker, create a property (make it strong and nonatomic) in your ViewController (or whatever class your using, and synthesize of course).
#property (nonatomic, strong) UIView *myDatePickerView;
#synthesize myDatePickerView;
then create a loadDatePickerView method
- (void) loadDatePickerView
{
UINib *nib = [UINib nibWithNibName:kNIBname bundle:[NSBundle mainBundle]];
NSArray *views = [nib instantiateWithOwner:self options:nil];
self.myDatePickerView = [views firstObject];
[myDatePickerView setFrame:CGRectMake(0, 318, 320, 162)];
[self.view addSubview:myDatePickerView];
}
implement the UITextFieldDelegate, and in the textFieldDidBeginEditing method call the loadDatePickerView method,
[self loadDatePickerView];
to make function create a property which is a UIDatePicker instance
#property (nonatomic,strong)
UIDatePicker *myDatePicker;
(synthesize of course)
now create an IBAction like so:
-(IBAction)datePickerValueChanged:(UIDatePicker *)sender
{
myDatePicker = [[myDatePickerView subviews] lastObject];
//now you can do whatever you want with the DatePicker
}
now connect the IBAction to the picker in the XIB file, that way the XIB is now the UIDatePicker instance you created in the VC, if you want it to disappear you can add a UITapGestureRecognizer (in the ViewDidLoad) and the selector will be another IBAction which removes myDatePickerView from its' superView like this:
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dropPicker:)];
[self.view addGestureRecognizer:tap];
[self datePickerValueChanged:myDatePicker];
}
-(IBAction)dropPicker:(id)sender
{
[myDatePickerView removeFromSuperview];
}

Related

Display datepicker when tapping on UISearchController (Searchbar)

I am using UISearchController programmatically, While tapping on Searchbar textField I want to be set Date picker as inputView
#property (strong, nonatomic) UISearchController *searchController;
References for text field : iPhone display date picker on UITextField touch
But unable to able to access Search bar Textfield. Please help.
You can get search textField using following code. Write it in viewDidLoad
UITextField *searchBarTextField = [self.searchController.searchBar valueForKey:#"_searchField"];
[searchBarTextField setInputView:datePicker];
Hope this will help you
First set delegate of UISearchBar then you can use following delegate method :
- (BOOL)searchBarShouldBeginEditing:(UISearchBar*)searchBar {
[self showDatePicker];
return NO;
}
-(void) showDatePicker {
UIDatePicker *datePicker = [[UIDatePicker alloc]init];
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker setDate:[NSDate date]];
[datePicker addTarget:self action:#selector(showSelectedDate:) forControlEvents:UIControlEventValueChanged];
}
- (void)showSelectedDate:(id)sender {
UIDatePicker *picker = (UIDatePicker*)self.date.inputView;
searchBar.text = [self formatDate:picker.date];
}
You can use any date formatter to show date in desired format.

iOS - can't get rid of keyboard

I have a text field for a user to enter a string, then another text field that when clicked shows a view that slides up with a date picker inside it.
If the user clicks on the first text field and enters a string using the keyboard and then hits the return button on the keyboard the keyboard goes away. But if they click on the date text field after entering a string in the first text field then the keyboard stays on the screen.
I have tried this:
#property (weak, nonatomic) IBOutlet UITextField *nameField;
#property (weak, nonatomic) IBOutlet UITextField *dateField;
....
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
return(![textField isEqual:self.dateField]);
}
It doesn't work.
I also tried this (this is triggered on begin editing when user clicks on dateField):
- (IBAction)dateTextFieldClicked:(id)sender {
[self.nameField resignFirstResponder];
}
and then this:
- (IBAction)dateTextFieldClicked:(id)sender {
[self.view endEditing:YES];
}
and neither of these works either. Is what I'm trying to do even possible? Should I just give up or is there some way that will work?
Try This ..
- (IBAction)dateTextFieldClicked:(id)sender {
[self.nameField resignFirstResponder];
[self.view endEditing:YES]; }
Try this in your viewDidLoad():
[self.nameTextField addTarget:self action:selector#(nameFieldClicked:) forControlEvents:UIControlEventEditingDidEnd]
And correct the parameter in your dataTextFieldClicked() as
- (IBAction)dateTextFieldClicked:(UITextField *)sender {
[sender resignFirstResponder];
}
I just be an iOS Developer when Apple launched Swift, which means the codes I wrote above maybe have some syntax error, but without logical error.
I hope my answer can help you.
There is a easy way, I had the same problem. Take the dateField as a UIButton, not as UITextField. In the Button action set this as follows:
- (IBAction)Date_set:(id)sender
{
[self.view endEditing:YES];
[self YourDatePickerset];
}
Set the title of the button when DatePicker value changed like this
- (void)pickerChanged:(id)sender
{
NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
[dateformate setDateFormat:#"dd LLL yyyy"]; // Date formater
NSString *date = [dateformate stringFromDate:[myPicker date]]; // Convert date to string
NSLog(#"date :%#",date);
[dob_btn setTitle:date forState:UIControlStateNormal];
}
Can you use this snippet and let me tell the result
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
make sure delegate is set to self for all textfields
Try this also
EDIT
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[dateField resignFirstResponder];
[nameField resignFirstResponder];
}

showing a UITextField that is a local variable vs a property in a custom view

I am mocking up a quick demo of a project but am having a problem with a UITextField.
The behavior that we want is that when a user clicks on a button, there should be a custom view that appears with a UITextField and a UIButton in a custom view that overlays the main view.
I have a custom view called Searchview and the following in the Searchview.m. The problem is that when the textField is a property, it doesn't show but when it is a local variable, it does show. Can anybody help me with what is going on so that the UITextField shows? Is how I am doing this even the right idea (custom UIView or custom UIControl or a modal controller)? Finally, would setNeedsDisplay be appropriate here?
thx in advance
#interface Searchview()
#property (nonatomic, weak) UITextField *textField;
#end
- (void)drawRect:(CGRect)rect
{
// this doesn't work
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 120.0f, 25.0f)];
self.textField.returnKeyType = UIReturnKeyDone;
self.textField.placeholder = #"Writer";
self.textField.borderStyle=UITextBorderStyleBezel;
[self.textField addTarget:self
action:#selector(textFieldDone:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[self addSubview: self.textField];
/* this works
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 120, 25)];
textField.returnKeyType = UIReturnKeyDone;
textField.placeholder = #"Writer";
textField.borderStyle=UITextBorderStyleBezel;
[textField addTarget:self
action:#selector(textFieldDone:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[self addSubview: textField];
*/
UIButton *mButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];
mButton.frame=CGRectMake(200.0f,10.0f,100.0f,37.0f);
[mButton setTitle:#"search" forState:UIControlStateNormal];
[mButton addTarget:self action:#selector(showSearchController:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:mButton];
[self setNeedsDisplay];
}
As a property - not showing:
As a local variable - showing:
#property (nonatomic, strong) UITextField *textField;
change the weak to strong and change the self.textFiled to _textField to have a try
And make sure your textField property not be released
It's pretty simple when you think about it. ARC (approximately) converts the following code:
self.weakProp = [[Foo alloc] init];
to the equivalent of the following "manually reference-counted" code:
Foo * temp = [[Foo alloc] init];
self.weakProp = temp;
[temp release];
Nothing is retaining it, so it is released.
I can only think of two reasons to have assign/weak IBOutlets:
For an outlet in a VC, so it doesn't retain a subview when its view is set to nil (e.g. on a memory warning). This is less relevant in iOS 6.0 since views are not automatically released on a memory warning (so if you do it, you can release them all explicitly).
For a view where the outlet points to a superview (and would cause a retain cycle). This is quite rare.
In general, I prefer strong IBOutlets: They might keep objects alive for a little longer than necessary, but they are safer than assign and more efficient than weak. Just watch out for retain cycles!

iOS - passing Sender (button) name to addSubview

I have a main view with 3 buttons. Clicking on any of the buttons adds a SubView.
The buttons have different titles and are all linked to IBAction "switchView"
The "switchView" code is below.
- (IBAction)switchView:(id)sender{
secondView *myViewController = [[secondView alloc] initWithNibName:#"secondView" bundle:nil];
[self.view addSubview:myViewController.view];
}
The "secondView" loads up correctly and everything works well.
The problem is I want to be able to know which button was the Sender.
I don't want to create 3 subviews, one for each button. The code and XIB would be absolutely the same>
The only difference would be a variable that I would like to set up in the second view (viewDidLoad method) depending on who is the Sender (which button was clicked)
Is this possible? Or I would need to create 3 subViews - one for each button?
Your help is greatly appreciated!
You can identify different buttons with the tag property.
e.g. with your method:
-(IBAction)switchView:(id)sender {
UIButton *button = (UIButton*)sender;
if (button.tag == 1) {
//TODO: Code here...
} else if (button.tag == 2) {
//TODO: Code here...
} else {
//TODO: Code here...
}
}
The tag property can be set via the InterfaceBuilder.
Hope this helps.
I think you can solve in 2 ways:
Create a property like:
#property (nonatomic, strong) IBOutlet UIButton *button1, *button2, *button3;
in your viewcontroller and link the buttons to them as referencing outlet on the XIB.
Give a different tag to each button on your xib and ask for the tag of the sender with UIButton *b=(UIButton*)sender; b.tag; like Markus posted in detail.
Solving my problem it all came down to transferring data between the mainView and subView.
In my mainView.h I declared an NSString and its #property
...
NSString *btnPressed;
}
#property(nonatomic, retain) NSString *btnPressed;
...
then in my mainView.m inside the switchView method I did this:
- (IBAction)switchView:(id)sender{
secondView *myViewController = [[secondView alloc] initWithNibName:#"secondView" bundle:nil];
btnPressed = [NSString stringWithFormat:#"%i", [sender tag]];
[myViewController setBtnPressed:self.btnPressed];
[self.view addSubview:myViewController.view];
}
This line in the code above actually takes care of transferring the data to the newly created subView:
[myViewController setBtnPressed:self.btnPressed];
Then in my secondView.h I declare exactly the same NSString *btnPressed and its #property (though this a completely different object than the one declared in main)
Then in my secondView.m I get the value of the button pressed I'm interested in.
- (void)viewDidLoad {
[super viewDidLoad];
int theValueOfTheButtonPressed = [self.btnPressed intValue];
}
This works well.
Don't forget to #synthesize btnPressed; as well as [btnPressed release]; in both mainView.m and secondView.m

UITapGestureRecognizer and making the keyboard disappear when tapping background

I created a form and the keypad (Numeric only) appears when entering data like your age.
I want the keyboard to disappear when the user taps the background and I want to add a "Done" button in the empty slot under the 7 (next to the zero). (im using the Number Pad keyboard)
I found this example but I have a few questions.
In
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
[aTextField1 resignFirstResponder];
[aTextField2 resignFirstResponder];
[aTextField3 resignFirstResponder];
}
If I have more than 1 text field in my form.
Will I need to write every textfield in the dismissKeyboard method?
Easy way to do this is to use the method provided in UIView
- (BOOL) endEditing:(BOOL)force;
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.
So just do this:
-(void)dismissKeyboard {
[self.view endEditing:YES];
}
and it will support any more text fields you add on your page (under that UIView of course)
You should only send dismissKeyboard to that textField that you are currently editing.
In your code you have got memory leak. Better use this one:
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
To check if UITextField is currently in edit mode you can check its property:
A Boolean value indicating whether the text field is currently in edit mode. (read-only)
#property(nonatomic, readonly, getter=isEditing) BOOL editing
For example, you have 3 text fields then dismissKeyboard will look something like this:
-(void)dismissKeyboard
{
UITextField *activeTextField = nil;
if ([textField1 isEditing]) activeTextField = textField1;
else if ([textField2 isEditing]) activeTextField = textField2;
else if ([textField3 isEditing]) activeTextField = textField3;
if (activeTextField) [activeTextField resignFirstResponder];
}
I use the same functionality in many of my apps. Rather than using the GestureRecognizer, I set my view up as a UIControl, rather than a UIView. You can still do the things you'd do with a UIView, but you can also assign IBActions to be performed when interacting with the view.
Here's how to do it:
In Interface Builder, select your view. Then, assign its class to UIControl. (It's probably set up as UIView currently.
In your ViewController for that view, write an IBAction method to detect backgroundTaps. Mine looks like this:
- (IBAction)backgroundTap:(id)sender
{
if ([textField1 isEditing]) {
[textField1 resignFirstResponder];
} else if ([textField2 isEditing]) {
[textField2 resignFirstResponder];
}
}
Finally, in Interface Builder, connect the IBAction you created to the UIControl.
Read this article, it may help you
Writing iOS 4 Code to Hide the iPhone Keyboard (Xcode 4)
Here i give common text field object. and asign reference to it in "textFieldShouldBeginEditing" method. that will common for all text field..
In this case, you need to dismiss one text field that will hide keyboard..
declare textfield object in .h file.
#interface RootViewController : UIViewController
{
IBOutlet UITextField* txt_common;
}
IN .m file
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
-(void)dismissKeyboard
{
NSLog(#"hi");
[txt_common resignFirstResponder];
}
#pragma mark TextField methods
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSLog(#"hi++++++++++++++++++");
txt_common=textField;
return YES;
}

Resources