XCode: отображение UIDatePicker, когда пользователь нажимает на UITextbox - PullRequest
3 голосов
/ 23 января 2012

Я уже исследовал эту тему до смерти и нашел людей, которые публиковали один и тот же вопрос на нескольких веб-сайтах, включая здесь в stackoverflow.

Я перепробовал все предложения, ноне удалось получить UIDatePicker для фактического отображения.Кажется, не имеет значения, какой подход я выберу.Я попытался использовать модель наследования, в которой я делю подкласс UITextBox и переопределяю его методы по умолчанию, чтобы отобразить UIDatePicker, а затем я удостоверяюсь, что в StoryBoard я установил класс своего элемента управления UITextView в этот пользовательский класс.Я попытался программно сгенерировать UIDatePicker, а также попытался перетащить его на представление в StoryBoard.Когда я пытаюсь использовать программный подход, ничего не отображается, а когда я пытаюсь перетащить его на StoryBoard, он отображается ВСЕГДА.Когда я устанавливаю его атрибут «скрытый», он скрывается, но тогда я не могу отобразить его, даже когда пытаюсь добавить код в метод textboxDidBeginEditing, который должен его показать.Я удостоверился, что установил свойство inputView UITextView равным моему элементу управления UIDatePicker.

Ничего не работает!Я не понимаю, почему Apple просто не сделала UIDatePicker одним из параметров по умолчанию в раскрывающемся списке Инспектора атрибутов для элемента управления UITextView.Это сделало бы это намного проще.

Ниже приведен фрагмент кода из моего файла классов реализации.

#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];
}

Вот как выглядит мой заголовочный файл ...

#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

Как я уже упоминал, другой подход, который я выбрал (т.е. создание подкласса UITextView), тоже не сработал.Я скопировал предоставленный код здесь именно так, как это было показано.Затем я добавил в свой проект пользовательские классы с именем «DateField» (и заголовок, и файлы реализации), а затем заменил объявление UITextBox для dueDate на DateField в моих файлах AddTaskViewController.h и AddTaskViewController.m и убедился, что ссылки StoryBoardбыли обновлены, выбрав DateField для класса элемента управления в Identity Inspector.

Независимо от того, что я делаю, я не могу отобразить UIDatePicker после нажатия на UITextView.Когда я устанавливаю точку останова, она срабатывает по методу dueDateDidBeginEditing, поэтому я знаю, что что-то срабатывает.Проблема в том, что я не понимаю, почему subView не отображается с помощью UIDatePicker.

Любая помощь будет принята с благодарностью, так как эта, казалось бы, простая задача, кажется, занимает гораздо больше времени, чем должна.Я мог бы делать такие вещи с закрытыми глазами и связанными руками за спиной в Java и C #, но все это так излишне сложно, когда дело доходит до Objective-C.Синтаксис действительно раздражает меня.

Так много квадратных скобок !!!Arghhhh !!!

Ответы [ 4 ]

10 голосов
/ 24 января 2012

Отображение UIDatePicker для inputView для UITextField относительно сложно по сравнению с отображением клавиатуры, но относительно легко по сравнению с возникшей проблемой.

Одна из первых проблемЯ заметил, что с вашим кодом, и это очень распространенная проблема для тех, кто не знаком с разработкой для iOS / Mac, это то, что вы пытаетесь установить свойство объекта, который еще не существует.Ввод self.dueDate.inputView = datePicker; в ваш initWithNibName:bundle: не будет работать, потому что представление еще не загружено, а dueDate является частью вашего представления.В target-c объект создается с помощью alloc & init.Init - это первый реальный вызов метода для любого объекта.На данный момент в жизни вашего контроллера вид еще не создан.Вызов метода, которому принадлежит self.dueDate.inputView = datePicker;, находится в методе viewDidLoad.Он вызывается именно тогда, когда он звучит так, как будто он вызывается, и ваше свойство dueDate будет правильно загружено в этот момент.Нет необходимости использовать пользовательский подкласс UITextField для отображения представления выбора даты для вашего текстового поля.Вот очень простой пример пользовательского класса представления ввода:

ExampleBasicDateInputView.h:

#import <UIKit/UIKit.h>

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

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

Затем загрузилось представлениевы бы использовали этот класс следующим образом:

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

И, как вы видите в файле .h, мы представили экземпляр средства выбора даты как свойство, чтобы вы могли установить стиль.и т.д. вроде так:

dateEntryView.datePicker.datePickerMode = UIDatePickerModeDate;

Очевидно, что это очень простой пример, но я думаю, что он показывает, что можно сделать.

10 голосов
/ 07 марта 2012

У меня была такая же проблема при использовании раскадровки.Вот как я решил это:

Обзор: Я выделяю и инициализирую свое свойство UIDatePicker в viewDidLoad :.Затем я устанавливаю свойство inputView моего текстового поля в свойстве datepicker.

Вот мой код: В TripViewController.h:

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

В 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;
}

Затем я реализую свой метод dateChanged, чтобы всякий раз, когдаколесо выбора даты перестает двигаться, мое текстовое поле обновлено.

- (void)dateChanged
{
NSDate *date = self.datePicker.date;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
self.dateField.text = [dateFormat stringFromDate:date];
}
1 голос
/ 21 февраля 2014

Это очень легко. Определяет делегат TextField (UITextFieldDelegate) в .h в viewDidLoad .m

myTextField.setDelegate = self;

В том же viewDidLoad связывает указатель даты с myTextField.

myTextField.inputView = myDatePicker;

Вы также можете делать аниме, но это самый простой способ.

1 голос
/ 23 января 2012

добавить делегат UITextField в файл .h для вызова этой функции при касании.затем используйте значение тега текстового поля, чтобы определить, что вы хотите сделать, когда поле выбрано.

-(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;
    }
}
...