UIDatePicker issue on UITextField(s) - ios

I am coding a TableViewController with a Section called Information where the user enter a name , a date , a description. My problem is that after i've done all the settings for the NSDate picker on the date's textfield , when i click on the description's textfield instead of keyboard i see the date picker and it stores date in the date's textfield.
.h file
#interface ViewControllerInfo : UITableViewController <UITableViewDelegate, UITextFieldDelegate>{
NSDate *date;
UIActionSheet *dateSheet;
}
#property (weak, nonatomic) IBOutlet UITextField *scadenza;
#property (weak, nonatomic) IBOutlet UITextField *dateTextField;
#property (nonatomic, retain)NSDate *date;
-(void)setDatario;
-(void)dismissDateSet;
-(void)cancelDate;
.m file (pointing only the functions needed):
-(void)setDatario;{
dateSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[dateSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 44, 0, 0);
UIDatePicker *datePicker = [[UIDatePicker alloc]initWithFrame:pickerFrame];
[datePicker setDatePickerMode:UIDatePickerModeDate];
[dateSheet addSubview:datePicker];
UIToolbar *controlToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, dateSheet.bounds.size.width, 44)];
[controlToolbar setBarStyle:UIBarStyleBlack];
[controlToolbar sizeToFit];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *setButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissDateSet)];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelDate)];
[controlToolbar setItems:[NSArray arrayWithObjects:spacer, setButton, cancelBtn, nil] animated:NO];
[dateSheet addSubview:controlToolbar];
[dateSheet showInView:self.view];
[dateSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
-(void)cancelDate{
[dateSheet dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)dismissDateSet{
NSArray *listofViews = [dateSheet subviews];
for (UIView *subview in listofViews){
if ([subview isKindOfClass:[UIDatePicker class]]){
self.date = [(UIDatePicker*)subview date];
}
[dateSheet dismissWithClickedButtonIndex:0 animated:YES];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
[dateTextField setText:[dateFormatter stringFromDate:self.date]];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
[self setDatario];
return NO;
}
I couldn't understand why is interesting also the description's texfield.
Question is : why the description's textfield is matched with the datepicker ?

Replace your textFieldShouldBeginEditing method like this
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField == scadenza) {
return YES;
}
else if(textField == scadenza){
[self setDatario];
return NO;
}
return YES;
}

Even better, put a custom UIButton (invisible) of the same size as the textfield right over the textfield. Set the textfield enabled attribute to NO and then show the picker when the button is tapped. When the user selects a date from the picker, update the text in the textfield. This way you won't have to manage the textfield's delegate. I have used both methods and the button is much cleaner and smoother for the user.

Related

Custom Views aren't dismissing keyboards?

Have tried [[self jotNotes] resignFirstResponder]; , have tried [self endEditing:YES];
So I have my NoteViewController, which inherits UIViewController, and tries to implement the delegate like so
#interface NOTEController : UIViewController <UITextViewDelegate>
#end
#implementation NOTEController
-(id)init {
self = [super init];
if (self) {
// self.delegate = self; //doesnt let me set this, so i assume i do not do that here
NOTEControllerView * mainView = [[NOTEControllerView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view = mainView; //just a plain custom uiview subclass its boring and not special
}
return self;
}
#end
and then in the mainView, i have a bunch of sub-views that are basically a square with a UITextView inside.
the squares class is like this, and they're the ones im trying to dismiss the keyboard from, heres where i set the delegate, the dismissKB method, and the UITextView code. Currently, it will log my keyboard method when pressing the done button, but the keyboard is still present. Would really appreciate if anyone could help me understand why
#interface NOTESubview : UIView <UITextFieldDelegate>
#property (nonatomic, weak) id<UITextFieldDelegate> delegate;
-(UITextView *)jotNotes;
#end
#implementation NOTESubview
-(id)initWithFrame:(CGRect)arg1 {
self = [super initWithFrame:arg1];
if (self) {
self.delegate = self;
[self addSubview:[self jotNotes]];
}
return self;
}
-(UITextView *)jotNotes {
UITextView * jotNotes = [[UITextView alloc] initWithFrame:CGRectMake(0, self.frame.size.height/5.7, self.frame.size.width, self.frame.size.height - self.frame.size.height/5.7)];
UIToolbar* keyboardTextViewBar = [[UIToolbar alloc] init];
keyboardTextViewBar.barStyle = UIBarStyleDefault;
[keyboardTextViewBar sizeToFit];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStylePlain target:self
action:#selector(dismissKB:)];
[keyboardTextViewBar setItems:[NSArray arrayWithObjects:flexSpace, doneButton, nil]];
jotNotes.inputAccessoryView = keyboardTextViewBar;
jotNotes.delegate = self.delegate;
return jotNotes;
}
-(void)dismissKB:(UIBarButtonItem *)sender {
//this will log, so im not sure why it wont resign the board no matter what i try
NSLog(#"keyboard attempted to dismiss by %#", sender);
[[self jotNotes] resignFirstResponder];
}
I suspect that when the dismissKB method is called, its actually not the one who is currently the first responder.
However, there's a trick where you can just "dismiss the keyboard" from anywhere in your app. You might wanna give it a try:
[[[[UIApplication sharedApplication] delegate] window] endEditing:YES];
Add the following line where you are trying to dismiss the keyboard:
[self endEditing:YES];

Datepicker crashes on textfield iOS 8

I have used UIDatePicker on the UITextField. I have press UITextField to select the date using datepicker 1st time(App working correct), 2nd Time when I have press again on UITextField to select the new date set on UITextField using UIDatePicker then application is crashes.
I am not using UITableView, I am using simple view that's viewController.
Please Help me...
Thanks
- (void)viewDidLoad
{
[super viewDidLoad];
form=[[NSDateFormatter alloc]init];
[form setDateFormat:#"MM-dd-yyyy"];
datePicker=[[UIDatePicker alloc]init];//Date picker
datePicker.frame=CGRectMake(0,0,320, 216);
datePicker.backgroundColor = [UIColor whiteColor];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
BOOL a;
if (textField.tag==10) {
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
UIView *popoverView = [[UIView alloc] init]; //view
popoverView.backgroundColor = [UIColor blackColor];
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker setMinuteInterval:5];
[datePicker setTag:10];
[datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:datePicker];
popoverContent.view = popoverView;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:popoverContent];
navigationController.delegate=self;
popoverController = [[UIPopoverController alloc]
initWithContentViewController:navigationController];
popoverController.delegate=self;
[popoverController setPopoverContentSize:CGSizeMake(320, 250) animated:NO];
[popoverController presentPopoverFromRect:textField.frame inView:self.addView permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
a=NO;
}
else
{
a=YES;
}
return a;
}
-(void)Result
{
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
formDay.dateFormat=#"MM-dd-yyyy";
NSString *day = [formDay stringFromDate:[datePicker date]];
self.edit_dob.text = day;
}
Error
*** Assertion failure in -[UIPickerTableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:], /SourceCache/UIKit/UIKit-3318.16.14/UITableView.m:9269
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource is not set'
I have share a screenshot. I have select date first time successfully and when I have press to reset new date on that textfield that time app crash.
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker setMinuteInterval:5];
[datePicker setTag:10];
[datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:datePicker];
You are repeating these operations every time the textfield is focused. This practice is plain wrong, and is a potential cause of various unexpected behavior like the one you encountered. The fact that it works for the first time makes me think that one of these unnecessarily repeated actions is the culprit. (I'd bet on the addTarget:forControlEvents: method call. This should never be done in any case. I don't even know what happens when you try to add the same target again.)
You should structure your code better to make these method calls only once, instead of multiple times like in the code you've shown (e.g. in viewDidLoad instead of textFieldShouldBeginEditing:) and most probably, the error will go away.
You need to retain the datepicker object i.e.:
#property(nonatomic,strong) UIDatePicker *datePicker;
in the .h file.
Here is updated code:
- (void)viewDidLoad
{
[super viewDidLoad];
form=[[NSDateFormatter alloc]init];
[form setDateFormat:#"MM-dd-yyyy"];
_datePicker=[[UIDatePicker alloc]init];//Date picker
_datePicker.frame=CGRectMake(0,0,320, 216);
_datePicker.backgroundColor = [UIColor whiteColor];
_datePicker.datePickerMode = UIDatePickerModeDate;
[_datePicker setMinuteInterval:5];
[_datePicker setTag:10];
[_datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
BOOL a;
if (textField.tag==10) {
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
UIView *popoverView = [[UIView alloc] init]; //view
popoverView.backgroundColor = [UIColor blackColor];
[popoverView addSubview:_datePicker];
popoverContent.view = popoverView;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:popoverContent];
navigationController.delegate=self;
UIPopoverController *popoverController = [[UIPopoverController alloc]
initWithContentViewController:navigationController];
popoverController.delegate=self;
[popoverController setPopoverContentSize:CGSizeMake(320, 250) animated:NO];
[popoverController presentPopoverFromRect:textField.frame inView:textField permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
a=NO;
}
else
{
a=YES;
}
return a;
}
-(void)Result
{
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
formDay.dateFormat=#"MM-dd-yyyy";
NSString *day = [formDay stringFromDate:[_datePicker date]];
_edit_dob.text = day;
}

Closing UIActionSheet

I have a UIActionSheet and I have added the following - UIPickerView and 2 BarButtonItems. I am trying to close the action sheet when someone clicks the Cancel Button (it is one of the bar button items).
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles: nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0,40,0,0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
UIToolbar *tools = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
tools.barStyle = UIBarStyleBlackOpaque;
[actionSheet addSubview:tools];
UIBarButtonItem *doneButton=[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleBordered target:self action:#selector(btnActinDoneClicked)];
doneButton.imageInsets=UIEdgeInsetsMake(200, 6, 50, 25);
UIBarButtonItem *CancelButton=[[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(btnActinCancelClicked)]; //this is where the problem is
NSArray *array = [[NSArray alloc]initWithObjects:CancelButton, doneButton, nil];
[tools setItems:array];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
I have added another method to dismiss the action sheet -
-(IBAction)btnActinCancelClicked:(id)sender{
[sender dismissWithClickedButtonIndex:0 animated:YES];
}
The problem is that the app crashes when the BarButton is clicked. I think the problem is caused where the CancelButton is declared and it is unable to send a message to the btnActinCancelClicked method, but I can't figure out how to fix it.
Thanks
Your method is this;
-(IBAction)btnActinCancelClicked:(id)sender
So you need to add it like this (because it receives a parameter);
#selector(btnActinCancelClicked:)
So for example, if a method had three parameters you'd call it #selector(myMethod:andX:andY:)
Also, to access your UIActionSheet (not entirely sure this will work);
UIActionSheet *acSheet = sender.superView;
//Check if it is the ActionSheet here then dismiss it
[acSheet dismissWithClickedButtonIndex:0 animated:YES];
It's not the sender you want to dismiss. It's the ActionSheet. You'll need a reference for that and change your code for something like:
- (IBAction)btnActinCancelClicked:(id)sender{
[self.actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}

UIPickerView with toolbar when UITextField is clicked

I'm trying to get a UIPickerView to display when a UITextField is clicked on by the user. I also want the UIPickerView to have a toolbar at the top with buttons to submit the selection and cancel.
Do I need to connect a UIPickerView in the interface builder, or connect an action somewhere else? I am also getting warnings when I build. One warning is under the resignFirstResponder. It says:
local declaration of age hides instance variable
There are several more warning similar to the one above for different variables.
Another warning is:
Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.
Here are my .h and .m files:
.h
#import <UIKit/UIKit.h>
#interface PracticePickerViewController : UIViewController <UITextFieldDelegate>{
IBOutlet UITextField *age;
IBOutlet UIPickerView *agePickerView;
IBOutlet UIActionSheet *actionSheet;
IBOutlet UIToolbar *pickerToolbar;
}
#end
.m
#import "PracticePickerViewController.h"
#implementation PracticePickerViewController
-(void)textFieldDidBeginEditing:(UITextField *)age{
[age resignFirstResponder];
actionSheet = [[UIActionSheet alloc] initWithTitle:#"Pick Your Age" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0,40,0,0);
UIPickerView *agePickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
agePickerView.showsSelectionIndicator = YES;
agePickerView.dataSource = self;
agePickerView.delegate = self;
[actionSheet addSubview:agePickerView];
pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,320,44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonPressed:)];
[barItems addObject:doneBtn];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelButtonPressed:)];
[barItems addObject:cancelBtn];
[pickerToolbar setItems:barItems animated:YES];
[actionSheet addSubview:pickerToolbar];
[actionSheet addSubview:agePickerView];
[actionSheet showInView:self.view];
[actionSheet setBounds:CGRectMake(0,0,320,485)];
}
local declaration of age hides instance variable
This means you've defined a variable name that is already used by a class variable (so in this case, you may have declared UITextField *age somewhere in the class, but you can't re-use variable name age in this class because the compiler will confuse it with the class variable).
Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.
You haven't made your PracticePickerViewController a UIActionsheetDelegate. To do this, you have change your interface header (PracticePickerViewController.h) to read:
#interface PracticePickerViewController : UIViewController <UITextFieldDelegate, UIActionsheetDelegate>{
Don't forget to implement the required delegate methods as well!
Finally, I strongly recommend you check out the ActionSheetPicker project.It's a drop-in class that has exactly the functionality you're trying to implement, so you can either replace your current code with that, or just use it as a reference to see how to implement the embedded ActionSheet inside the UIPickerView correctly. Hope all that helps!

iPad - Showing action sheet with picker view

I'm adding picker view to action sheet which is working fine in iPhone. But in iPad, i'm not seeing the action sheet. I'm seeing one small rectangle at the middle of the screen in iPad. Here's the code that I wrote:
NSString *actionSheetTitle = #"Select Date of Birth";
UIActionSheet *dateSheet = [[UIActionSheet alloc] initWithTitle:actionSheetTitle
delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil
otherButtonTitles:#"Done",nil];
dateSheet.delegate = self;
dateSheet.actionSheetStyle = UIActionSheetStyleAutomatic;
dateSheet.destructiveButtonIndex = 0; // make the second button red (destructive)
dateSheet.tag = 100;
//Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0,185,0,0)];
pickerView.datePickerMode = UIDatePickerModeDate;
[pickerView addTarget:self action:#selector(dateSelectionChanged:) forControlEvents:UIControlEventValueChanged];
[dateSheet addSubview:pickerView];
[dateSheet showInView:self.view];
[dateSheet setBounds:CGRectMake(0,0,320,700)];
self.tempDob = self.dob;
if (self.editPatientDetails)
{
NSDateFormatter* dtFormatter = [[NSDateFormatter alloc] init];
[dtFormatter setDateFormat:#"MM/dd/yyyy"];
NSDate* dateSelected = [dtFormatter dateFromString:self.dob];
[dtFormatter release];
[pickerView setDate:dateSelected animated:YES];
}
[pickerView release];
[dateSheet release];
Action sheet is shown as picker view in iPad. Its the expected behavior.

Resources