ios XCode:当用户单击 UITextbox 时显示 UIDatePicker

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8974131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:26:50  来源:igfitidea点击:

XCode: Displaying a UIDatePicker when user clicks on UITextbox

iphoneiosxcodeuitextviewuidatepicker

提问by Ami Schreiber

I have already researched this topic to death and found people posting the exact same question on a number of websites including right herein stackoverflow.

我已经研究了这个话题死亡,发现有人发帖对一些网站,包括权完全一样的问题,这里的计算器。

I have tried all of the suggestions but have been unable to get the UIDatePicker to actually display. It doesn't seem to matter what approach I take. I've tried using the inheritance model where I subclass the UITextBox control and override it's default methods in order to display the UIDatePicker and then I make sure that in StoryBoard I set the class of my UITextView control to be that custom class. I've tried programmatically generating the UIDatePicker and also tried dragging it onto the view in StoryBoard. When I try the programmatic approach nothing is displayed and when I try dragging it onto the StoryBoard it ALWAYS displays. When I set it's attribute to "hidden" it hides but then I can't get it to show even when I try to add code to the textboxDidBeginEditingmethod that should unhide it. I've made sure to set the UITextView's inputView property equal to my UIDatePicker control.

我已经尝试了所有的建议,但一直无法让 UIDatePicker 实际显示。我采取什么方法似乎并不重要。我已经尝试使用继承模型,我将 UITextBox 控件子类化并覆盖它的默认方法以显示 UIDatePicker,然后确保在 StoryBoard 中我将 UITextView 控件的类设置为该自定义类。我试过以编程方式生成 UIDatePicker 并尝试将它拖到 StoryBoard 中的视图上。当我尝试编程方法时,什么也没有显示,当我尝试将它拖到 StoryBoard 上时,它总是显示。当我将它的属性设置为“隐藏”时,它会隐藏,但即使我尝试将代码添加到textboxDidBeginEditing应该取消隐藏它的方法。我确保将 UITextView 的 inputView 属性设置为等于我的 UIDatePicker 控件。

Nothing works! I don't understand why Apple didn't just make the UIDatePicker one of the default options in the drop down list in the Attributes Inspector for the UITextView control. That would have made this so much easier.

没有任何作用!我不明白为什么 Apple 不只是将 UIDatePicker 设为 UITextView 控件的 Attributes Inspector 下拉列表中的默认选项之一。这会让这件事变得容易得多。

Below is some of the code from my implementation class file.

下面是我的实现类文件中的一些代码。

#import "AddTasksViewController.h"

@implementation AddTasksViewController

@synthesize dueDate;
@synthesize description;
@synthesize shortTitle;
@synthesize datePicker;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        self.dueDate.inputView = datePicker;

    }
    return self;
}

- (IBAction)dueDateDidBeginEditing:(UITextView *)textField 
{  
    [textField resignFirstResponder];
    [datePicker setFrame:CGRectMake(0,200,320,120)];
    [datePicker addTarget:self action:@selector(done) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:datePicker];
}

Here is what my header file looks like...

这是我的头文件的样子...

#import <UIKit/UIKit.h>

@interface AddTasksViewController : UIViewController

@property (nonatomic, copy) IBOutlet UITextView      *dueDate;
@property (nonatomic, copy) IBOutlet UITextView      *description;
@property (nonatomic, copy) IBOutlet UITextView      *shortTitle;
@property (nonatomic, retain) IBOutlet UIDatePicker    *datePicker;

- (IBAction)doneEditing:(id)sender;
- (IBAction)dateChanged:(id)sender;
- (IBAction)dueDateDidBeginEditing:(UITextView *)textField;

@end

As I've already mentioned, the other approach that I took (i.e. subclassing UITextView) didn't work either. I copied the code provided hereexactly as it was show. I then added the custom classes called "DateField" to my project (both the header and implementation files) and then replaced the UITextBox declaration for the dueDate with DateField in both my AddTaskViewController.h and AddTaskViewController.m files and made sure that the StoryBoard references were updated to by selecting DateField for the control's class in the Identity Inspector.

正如我已经提到的,我采用的另一种方法(即子类化 UITextView)也不起作用。我完全按照显示复制了此处提供的代码。然后我将名为“DateField”的自定义类添加到我的项目(头文件和实现文件),然后在我的 AddTaskViewController.h 和 AddTaskViewController.m 文件中用 DateField 替换了 DueDate 的 UITextBox 声明,并确保 StoryBoard 引用通过在身份检查器中为控件的类选择 DateField 来更新。

No matter what I do I cannot get the UIDatePicker to display upon clicking on the UITextView. When I set a breakpoint it does hit the dueDateDidBeginEditingmethod so I know that something is being triggered. The problem is that I don't understand why a subView is not being showing with the UIDatePicker.

无论我做什么,我都无法在单击 UITextView 时显示 UIDatePicker。当我设置断点时,它确实命中了dueDateDidBeginEditing方法,所以我知道正在触发某些事情。问题是我不明白为什么子视图没有与 UIDatePicker 一起显示。

Any help would be greatly appreciated as this seemingly straightforward task seems to be taking much, much longer than it should. I could do this sort of stuff with my eyes closed and hands tied behind my back in Java and C# yet everything is so unnecessarily complicated when it comes to Objective-C. The syntax really irritates me.

任何帮助将不胜感激,因为这个看似简单的任务似乎比它应该花费的时间要长得多。在 Java 和 C# 中,我可以闭上眼睛,双手绑在背后做这种事情,但是当涉及到 Objective-C 时,一切都变得不必要地复杂了。语法真的让我很恼火。

So many square brackets!!! Arghhhh!!!

这么多方括号!!!啊啊啊!!!

回答by NJones

Showing a UIDatePickerfor the inputViewof a UITextFieldis relatively hard compared to showing a keyboard, but relatively easy compared to the trouble you've had.

呈现出UIDatePickerinputView一个UITextField相对硬相比呈现出的键盘,但比较容易比较,你有麻烦。

One of the first problems I noticed with your code, and it's a very common problem with those new to iOS/Mac development, is that you are attempting to set the property of an object that doesn't exist yet. Putting "self.dueDate.inputView = datePicker;" in your initWithNibName:bundle:will not work because the view has not yet loaded, and dueDateis part of your view. In objective-c an object is instantiated with alloc & init. Init is the first real method call to any object. At this point in your view controller's life the view has not been created yet. The method call where self.dueDate.inputView = datePicker;belongs is in the viewDidLoadmethod. It is called exactly when it sounds like it's called, and your dueDateproperty will be properly loaded at that point. There is no need to use a custom subclass of UITextFieldto display a date picking view for for your text field. Here is a very basic example of a custom input view class:

我注意到您的代码的第一个问题之一,也是 iOS/Mac 开发新手的一个非常常见的问题,就是您试图设置尚不存在的对象的属性。将“ self.dueDate.inputView = datePicker;”放在您initWithNibName:bundle:的视图中将不起作用,因为视图尚未加载,并且dueDate是您视图的一部分。在objective-c 中,一个对象是用alloc & init 实例化的。Init 是对任何对象的第一个真正的方法调用。此时在您的视图控制器生命周期中,视图尚未创建。self.dueDate.inputView = datePicker;所属的方法调用在viewDidLoad方法中。它在听起来像是被调用的时候被准确地调用,并且您的dueDate属性将在那时正确加载。不需要使用自定义的子类UITextField为您的文本字段显示日期选择视图。这是自定义输入视图类的一个非常基本的示例:

ExampleBasicDateInputView.h:

ExampleBasicDateInputView.h:

#import <UIKit/UIKit.h>

@interface ExampleBasicDateInputView : UIView
@property (strong,nonatomic) UIDatePicker *datePicker;
@end

ExampleBasicDateInputView.m:

ExampleBasicDateInputView.m:

#import "ExampleBasicDateInputView.h"

@implementation ExampleBasicDateInputView{
    UITextField *_inputField; // ivar to store the textfield currently being edited
}
@synthesize datePicker = _datePicker;
// TARGET METHODS
-(void)pickerValueChanged:(UIDatePicker *)picker{
    _inputField.text = self.datePicker.date.description; // set text to date description
}
-(void)viewDoubleTapped:(UITapGestureRecognizer *)tapGR{
    [_inputField resignFirstResponder]; // upon double-tap dismiss picker
}
-(void)textFieldBeganEditing:(NSNotification *)note{
    _inputField = note.object; // set ivar to current first responder
}
-(void)textFieldEndedEditing:(NSNotification *)note{
    _inputField = nil; // the first responder ended editing CRITICAL:avoids retain cycle
}
// INITI METHODS
-(void)initializationCodeMethod{
    _datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 320, 0)];// All pickers have preset height
    self.bounds = _datePicker.frame; // Make our view same size as picker
    [self addSubview:_datePicker];
    [_datePicker addTarget:self action:@selector(pickerValueChanged:) forControlEvents:UIControlEventValueChanged]; // register to be notified when the value changes
        // As an example we'll use a tap gesture recognizer to dismiss on a double-tap
    UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewDoubleTapped:)];
    tapGR.numberOfTapsRequired = 2; // Limit to double-taps
    [self addGestureRecognizer:tapGR];
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center addObserver:self selector:@selector(textFieldBeganEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil]; // Ask to be informed when any textfield begins editing
    [center addObserver:self selector:@selector(textFieldEndedEditing:) name:UITextFieldTextDidEndEditingNotification object:nil]; // Ask to be informed when any textfield ends editing
}
-(id)init{
    if ((self = [super init])){
        [self initializationCodeMethod];
    }
    return self;
}
-(id)initWithFrame:(CGRect)frame{
    if ((self = [super initWithFrame:frame])){
        [self initializationCodeMethod];
    }
    return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
    if ((self = [super initWithCoder:aDecoder])){
        [self initializationCodeMethod];
    }
    return self;
}
-(void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidEndEditingNotification object:nil];
}
@end

Then in view did load you would use this class like this:

然后在视图中加载你会像这样使用这个类:

ExampleBasicDateInputView *dateEntryView = [[ExampleBasicDateInputView alloc] init];
self.dueDate.inputView = datePickerView;

And as you see in the .hfile we've exposed the date picker instance as a property so you can set the style. etc. like so:

正如您在.h文件中看到的,我们将日期选择器实例公开为一个属性,以便您可以设置样式。等等,像这样:

dateEntryView.datePicker.datePickerMode = UIDatePickerModeDate;

Obviously this is a very basic example, but I think it shows what can be done.

显然这是一个非常基本的例子,但我认为它显示了可以做什么。

回答by djblue2009

I had the same issue using Storyboard. Here is how I resolved it:

我在使用 Storyboard 时遇到了同样的问题。这是我解决它的方法:

Overview: I alloc and initialize my UIDatePicker property in viewDidLoad:. I then set the inputView property of my textfield to my datepicker property.

概述:我在 viewDidLoad: 中分配并初始化了我的 UIDatePicker 属性。然后我将我的文本字段的 inputView 属性设置为我的 datepicker 属性。

Here is my code: In TripViewController.h:

这是我的代码:在 TripViewController.h 中:

@property (nonatomic,strong) IBOutlet UIDatePicker *datePicker;

In TripViewController.m:

在 TripViewController.m 中:

@synthesize datePicker;
...
-(void)viewDidLoad {
...
self.datePicker = [[UIDatePicker alloc]init];
[self.datePicker addTarget:self action:@selector(dateChanged) forControlEvents:UIControlEventValueChanged];
self.dateField.inputView = self.datePicker;
}

I then implement my method, dateChanged so that whenever the date picker wheel stops moving, my textfield is updated.

然后我实现了我的方法 dateChanged,这样每当日期选择器轮停止移动时,我的文本字段就会更新。

- (void)dateChanged
{
NSDate *date = self.datePicker.date;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
self.dateField.text = [dateFormat stringFromDate:date];
}

回答by Padin215

add UITextField's delegate in .h file to call this function when touched. then use the text field's tag value to determine what you want to do when the field is selected.

在 .h 文件中添加 UITextField 的委托以在触摸时调用此函数。然后使用文本字段的标记值来确定选择该字段时要执行的操作。

-(BOOL) textFieldShouldBeginEditing:(UITextField *) textField 
{
    activeTextField = textField;

    if (textField.tag == 1) 
    {
        self.datePicker.datePickerMode = UIDatePickerModeDate;
        self.isDatePicker = TRUE;
        self.tempTextField = textField;
        [self showPicker];
        return NO;
    }
    else if (textField.tag == 2) 
    {
        self.datePicker.datePickerMode = UIDatePickerModeTime;
        self.isDatePicker = TRUE;
        self.tempTextField = textField;
        [self showPicker];

        return NO;
    }
    else if (textField.tag == 3)
    {
        self.isDatePicker = FALSE;
        self.tempTextField = textField;
        [self showPicker];
        return NO;
    }
    else
    {
        self.tempTextField = textField;
        return YES;
    }
}

回答by oscar castellon

It is very easy. Defines delegate TextField (UITextFieldDelegate) in the .h in the viewDidLoad .m

这很容易。在 viewDidLoad .m 的 .h 中定义委托 TextField (UITextFieldDelegate)

myTextField.setDelegate = self;

In the same viewDidLoad associates the datePicker to myTextField.

在同一个 viewDidLoad 中,datePicker 与 myTextField 相关联。

myTextField.inputView = myDatePicker;

You can also do anime, but this is the easiest way.

你也可以做动画,但这是最简单的方法。