How can I display a datetimepicker control on tap of a textbox?
I have a user interface that has arrival and departure text fields, and when a user clicks on arrival textbox it should bring up a datetimepicker control up instead of a keyboard and the same with the departure textbox.
You can use inputView and inputAccessoryView properties of the text field for this. Create the date picker and set it to the input views of the two text fields. Also create another view for the Done button and it as their accessory view. You will need that button to dismiss the input view.
The Done button must be wired up to function which basically does this –
if ( [textField1 isFirstResponder] ) {
[textField1 resignFirstResponder];
} else if ( [textField2 isFirstResponder] ) {
[textField2 resignFirstResponder];
}
Another option would be to subclass UITextField and override inputView and inputAccessoryView. This is the way to go when there are loads of them.
Example
#interface CustomKeyboardAppDelegate : NSObject <UIApplicationDelegate> {
...
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITextField *textField;
#property (nonatomic, retain) IBOutlet UIToolbar *accessoryView;
#property (nonatomic, retain) IBOutlet UIDatePicker *customInput;
- (IBAction)dateChanged:(id)sender;
- (IBAction)doneEditing:(id)sender;
#end
In the XIB, Pull out a UIToolbar and a UIDatePicker but don't attach it to the view. Connect the outlets appropriately. dateChanged: responds to changes in the date picker and doneEditing: is called when the Done button in the tool bar is clicked. Connect them too. The methods are implemented as listed below.
#implementation CustomKeyboardAppDelegate
#synthesize window=_window;
#synthesize textField = _textField;
#synthesize accessoryView = _accessoryView;
#synthesize customInput = _customInput;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.textField.inputView = self.customInput;
self.textField.inputAccessoryView = self.accessoryView;
...
}
...
- (IBAction)dateChanged:(id)sender {
UIDatePicker *picker = (UIDatePicker *)sender;
self.textField.text = [NSString stringWithFormat:#"%#", picker.date];
}
- (IBAction)doneEditing:(id)sender {
[self.textField resignFirstResponder];
}
#end
The last two methods will bloat up as more text fields depend on this picker.
Very simple, in ViewController.h put the UITextFieldDelegate after in viewDidLoad.
txtFecha.delegate = self;
datePicker = [[UIDatePicker alloc]init];
[datePicker setDatePickerMode:UIDatePickerModeDate];
self.txtFecha.inputView = datePicker;
In viewDidLoad of ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
UIDatePicker *datePicker = [[UIDatePicker alloc]init];
[datePicker setDate:[NSDate date]];
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker addTarget:self action:#selector(dateTextField:) forControlEvents:UIControlEventValueChanged];
[txtFieldBranchYear setInputView:datePicker];
}
Add one method in your ViewController
-(void) dateTextField:(id)sender
{
UIDatePicker *picker = (UIDatePicker*)txtFieldBranchYear.inputView;
[picker setMaximumDate:[NSDate date]];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
NSDate *eventDate = picker.date;
[dateFormat setDateFormat:#"dd/MM/yyyy"];
NSString *dateString = [dateFormat stringFromDate:eventDate];
txtFieldBranchYear.text = [NSString stringWithFormat:#"%#",dateString];
}
txtFieldBranchYear is an outlet of UITextField
There's a really useful class I found - the blog post is here: http://www.pietrorea.com/2012/07/how-to-hide-the-cursor-in-a-uitextfield/ but it basically uses the inputView/inputAccessory view as well. The kicker is that the UILabel, at least for what I was doing, was exactly what I needed.
open date picker on click on textField swift 3.0
add UITextFieldDelegate and
set delegate on ViewDidload()
tfDate.delegate = self
//MARK:- TextField Delegate
//MARK:-
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
//MARK:- DatePicker
//MARK:-
func textFieldDidBeginEditing(_ textField: UITextField) {
self.callDatePicker(textField: tfDate)
}
func callDatePicker(textField:UITextField){
let datePickerView : UIDatePicker = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.date
textField.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(MyViewController.handleDatePicker), for: .valueChanged)
}
var str:String = ""
var str1:String = ""
var strStartDate:Date!
var strEndDate:Date!
func handleDatePicker(sender: UIDatePicker) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
print("Date :: \(dateFormatter.string(from: sender.date))")
tfDate.text = dateFormatter.string(from: sender.date)
}
Related
I'm using MagicalRecord to store a list of dates and descriptions in a Core Data entity's attribute and I need to display them to a UILabel in a UITableViewCell. But my app crashes whenever I access the UITableViewController. I'm not sure why it crashes but I believe it's because of the NSDate object. Please help.
Time+CoreDataProperties.h
#import "Time.h"
NS_ASSUME_NONNULL_BEGIN
#interface Time (CoreDataProperties)
#property (nullable, nonatomic, retain) NSString *title;
#property (nullable, nonatomic, retain) TimeDetails *timeDetails;
#end
NS_ASSUME_NONNULL_END
UITableViewController
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndex:indexPath];
return cell;
}
-(void) configureCell: (UITableViewCell *) cell atIndex:(NSIndexPath *) indexPath
{
Time *time = self.times[indexPath.row];
UILabel *titleLabel = (UILabel *) [cell viewWithTag:100];
titleLabel.text = time.title;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *dateDetails = [dateFormatter stringFromDate:time.timeDetails.date];
NSLog(#"Date is %#",dateDetails);
UILabel *dateLabel = (UILabel *) [cell viewWithTag:101];
dateLabel.text = dateDetails;
}
Error message:-
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key dateLabel2.'
Wherever you have defined the cell, in your storyboard or an XIB, you have connected an outlet to a label but that outlet doesn't exist. The outlet is called dateLabel2.
Go through all the labels in the cell, check the outlet connections on them and remove any that are invalid.
I have a NSObject called GettingHere which has a NSString *content.
I then have a UIViewController on which I create a button programatically as follows (this button working as intended):
byAirButton = [UIButton buttonWithType:UIButtonTypeCustom];
byAirButton.tag = 1;
byAirButton.frame = CGRectMake(25, 140, 280.f, 40.f);
UIImage *airButton = [UIImage imageNamed:#"gettingHereByAirButton.png"];
[byAirButton setBackgroundImage:airButton forState:UIControlStateNormal];
[self.view addSubview:byAirButton];
[byAirButton addTarget:self action:#selector(byAirButtonClicked) forControlEvents:UIControlEventTouchUpInside];
For the action:#selector(byAirButtonClicked), I do the following. gettingHere is an instance of the GettingHere object.
- (void) byAirButtonClicked
{
gettingHere.content = #"This is how to get here by Air";
NSLog(#"Content: %#", gettingHere.content);
[self performSegueWithIdentifier:#"gettingHereSegue" sender:self];
}
The idea is to set the content for my GettingHere object and then just call that from the next view (GettingHereViewController) when the user clicks the byAirButton.
This NSLog shows that content is being set.
In my prepareForSegue, I do the following:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"gettingHereSegue"])
{
NSLog(#"Content to be passed: %#", gettingHere.content);
GettingHereViewController *vc = (GettingHereViewController *)segue.destinationViewController;
vc.gettingHere.content = gettingHere.content;
}
}
The segue works fine, but the NSLog shows my gettingHere object values as being (null).
Can anyone tell me where I am going wrong please? I have stepped through it several times but can't figure out where I am going wrong.
EDIT: Here is how I instantiate the GettingHere Object.
In the SubNavViewController.h
#import "GettingHereContent.h"
#interface SubNavViewController : UIViewController
#property GettingHereContent *gettingHere;
In the SubNavViewController.m
#import "SubNavViewController.h"
#import "GettingHereViewController.h"
#import "GettingHereContent.h"
#interface SubNavViewController ()
#end
#implementation SubNavViewController
#synthesize gettingHere;
And here is how I create the GettingHere Object:
GettingHere.h
#import <Foundation/Foundation.h>
#interface GettingHereContent : NSObject
#property (nonatomic, strong) NSString *content;
#end
GettingHere.m
#import "GettingHereContent.h"
#implementation GettingHereContent
#synthesize content;
#end
You never alloc init your gettingHere property. Try this in your init method of your VC
gettingHere = [[GettingHereContent alloc] init];
Also don't forget to release it: answer from here: alloc + init with synthesized property - does it cause retain count to increase by two?
#interface Foo : Bar {
SomeClass* bla;
}
#property (nonatomic, retain) SomeClass* bla;
#end
#implementation Foo
#synthesize bla;
-(id)init {
...
bla = [[SomeClass alloc] init];
...
}
-(void)dealloc {
[bla release];
...
[super dealloc];
}
I have an UITableView that contains 2 buttons for each UITableviewCell.
How to hide the buttons when the UITableview is in edit mode?
Thanks
Just wanted to update this thread with a much simpler solution. In order to hide specific elements in a custom subclass of UITableViewCell, simply override one method for UITableViewCell (implementation in Swift):
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
// Customize the cell's elements for both edit & non-edit mode
self.button1.hidden = editing
self.button2.hidden = editing
}
This will be called automatically for each cell after you call the parent UITableView's -setEditing:animated: method.
I suggest you to subclass UITableViewCell and add the buttons as properties, then set their hiddenproperty to YES:
#interface CustomCell: UITableViewCell
{
UIButton *btn1;
UIButton *btn2;
}
#property (nonatomic, readonly) UIButon *btn1;
#property (nonatomic, readonly) UIButon *btn2;
- (void)showButtons;
- (void)hideButtons;
#end
#implementation CustomCell
#synthesize btn1, btn2;
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStrig *)reuseId
{
if ((self = [super initWithStyle:style reuseidentifier:reuseId]))
{
btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// etc. etc.
}
return self;
}
- (void) hideButtons
{
self.btn1.hidden = YES;
self.btn2.hidden = YES;
}
- (void) showButtons
{
self.btn1.hidden = NO;
self.btn2.hidden = NO;
}
#end
And in your UITableViewDelegate:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
[(CustomCell *)[tableView cellForRowAtIndexPath:indexPath] hideButtons];
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
[(CustomCell *)[tableView cellForRowAtIndexPath:indexPath] showButtons];
}
Hope it helps.
I've spent many hours trying to figure how to do this:
Having a placemark/annotation in the centerCoordinate of your mapView, when you scroll the map, the placemark should always stays in the center.
I've seen another app doing this too!
Found my question in How to add annotation on center of map view in iPhone?
There's the answer :
If you want to use an actual annotation instead of just a regular view positioned above the center of the map view, you can:
use an annotation class with a settable coordinate property (pre-defined MKPointAnnotation class eg). This avoids having to remove and add the annotation when the center changes.
create the annotation in viewDidLoad
keep a reference to it in a property, say centerAnnotation
update its coordinate (and title, etc) in the map view's regionDidChangeAnimated delegate method (make sure map view's delegate property is set)
Example:
#interface SomeViewController : UIViewController <MKMapViewDelegate> {
MKPointAnnotation *centerAnnotation;
}
#property (nonatomic, retain) MKPointAnnotation *centerAnnotation;
#end
#implementation SomeViewController
#synthesize centerAnnotation;
- (void)viewDidLoad {
[super viewDidLoad];
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = mapView.centerCoordinate;
pa.title = #"Map Center";
pa.subtitle = [NSString stringWithFormat:#"%f, %f", pa.coordinate.latitude, pa.coordinate.longitude];
[mapView addAnnotation:pa];
self.centerAnnotation = pa;
[pa release];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
centerAnnotation.coordinate = mapView.centerCoordinate;
centerAnnotation.subtitle = [NSString stringWithFormat:#"%f, %f", centerAnnotation.coordinate.latitude, centerAnnotation.coordinate.longitude];
}
- (void)dealloc {
[centerAnnotation release];
[super dealloc];
}
#end
Now this will move the annotation but not smoothly. If you need the annotation to move more smoothly, you can add a UIPanGestureRecognizer and UIPinchGestureRecognizer to the map view and also update the annotation in the gesture handler:
// (Also add UIGestureRecognizerDelegate to the interface.)
// In viewDidLoad:
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
panGesture.delegate = self;
[mapView addGestureRecognizer:panGesture];
[panGesture release];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
pinchGesture.delegate = self;
[mapView addGestureRecognizer:pinchGesture];
[pinchGesture release];
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
centerAnnotation.coordinate = mapView.centerCoordinate;
centerAnnotation.subtitle = [NSString stringWithFormat:#"%f, %f", centerAnnotation.coordinate.latitude, centerAnnotation.coordinate.longitude];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
//let the map view's and our gesture recognizers work at the same time...
return YES;
}
The navigationbar is failing to appear, works fine in a UITableView, but fails inside a popoverController
Initiate a popover popoverController in UIViewController
-(IBAction) btnShowMovies:(id) sender {
if (self.popoverController == nil) {
teamAController *movies =
[[teamAController alloc]
initWithNibName:#"teamAController"
bundle:[NSBundle mainBundle]];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:movies];
popover.delegate = self;
[movies release];
self.popoverController = popover;
[popover release];
}
CGRect popoverRect = [self.view convertRect:[btn frame]
fromView:[btn superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 100);
[self.popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
}
teamAController.h
#interface teamAController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *tableView;
NSArray *theArray;
}
#property (nonatomic, retain) NSArray *theArray;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
-(void) createArray;
teamAController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title= #"FooBarExtreme";
self.contentSizeForViewInPopover = CGSizeMake(250.0, 300.0);
[self createArray];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
Everything works, I have lovely table with images etc, correct sized and placed popover just no title bar..... ?
I found the solution/problem by following the tutorial at http://mobiforge.com/designing/story/using-popoverview-ipad-app-development.
Worth noting that I found this the most comprehensive one on creating uiPopoverController with uiNavigationBar elements from UIButtons.
The issue is that the popover itself belongs to the view that calls it. The content is derived from the xlib/view you load into it. But not the titlebar. You call that in the parent view view.
This code is in the main view and is called from the UIButton
// BookMarksViewController is the class that contains the code/xib for the popover's content
// Of overarching importance is creating it as a UITableViewController
if (self.popoverController == nil) {
BookMarksViewController *bookMarksViewController =
[[BookMarksViewController alloc]
initWithNibName:#"BookMarksViewController"
bundle:[NSBundle mainBundle]];
// Here's the rub: because in effect this view is controlling the popover
// we have to assign nav bar stuff here. Sigh.
bookMarksViewController.navigationItem.title = #"Territories";
UINavigationController *navController =
[[UINavigationController alloc]
initWithRootViewController:bookMarksViewController];
bookMarksViewController.contentSizeForViewInPopover = CGSizeMake(320, 400);
UIPopoverController *popover =
[[UIPopoverController alloc]
initWithContentViewController:navController];
popover.delegate = self;
[bookMarksViewController release];
[navController release];
self.popoverController = popover;
[popover release];
}
CGRect sourceRect = [self.view convertRect:[btn frame] fromView:[btn superview]];
[self.popoverController presentPopoverFromRect:sourceRect
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];