Zhigang An
Zhigang An

Reputation: 294

How to show year only in NSDatePicker

I want to show year component only in a NSDatePicker.

I tried set/add NSDateFormatter to NSDatePicker, but with no luck. (By dragging a NSDateFormatter to NSDatePicker in nib)

Is there any way to achieve this without subclassing NSDatePicker or NSTextField? Thank you!

Upvotes: 1

Views: 674

Answers (3)

Pierre Bernard
Pierre Bernard

Reputation: 3198

-[NSDatePicker setDatePickerElements:] can no longer be tricked into showing year only.

A year-only NSDatePicker can be obtained by configuring a year-month picker and subclassing NSDatePickerCell to prevent it from creating the month and separator fields:

- (void)_addSubfieldForElement:(int)arg1 withDateFormat:(id)arg2 referenceStrings:(id)arg3
{
    if ((arg1 == 6) || (arg1 == 100)) {
        return;
    }

    [super _addSubfieldForElement:arg1 withDateFormat:arg2 referenceStrings:arg3]; // Private API
}

Please file bug reports with Apple to request a year-only variant of NSDatePicker. I also requested a week-of-year picker.

Upvotes: 1

Zhigang An
Zhigang An

Reputation: 294

After diving into Apple's Documentation, I found the solution and want to post it here, in case it is useful for someone else.

No need to subclass NSDatePicker, there is a method - (void)setDatePickerElements:(NSDatePickerElementFlags)elementFlags which specifies which element the date picker would display. elementFlags is a constant, defined by a enum as:

enum {
   NSHourMinuteDatePickerElementFlag       = 0x000c,
   NSHourMinuteSecondDatePickerElementFlag = 0x000e,
   NSTimeZoneDatePickerElementFlag         = 0x0010,
   NSYearMonthDatePickerElementFlag        = 0x00c0,
   NSYearMonthDayDatePickerElementFlag     = 0x00e0,
   NSEraDatePickerElementFlag              = 0x0100,
};
typedef NSUInteger NSDatePickerElementFlags;

When looking at those constants, I find it is just a bit mask. Bit place and the corresponding calendar elements is as follows:

15 - 9 bit: Unknown. Maybe unused.

8 bit: Era. (Would not display anything if has a 4-digit year format.)

7 bit: Year.

6 bit: Month.

5 bit: Day.

4 bit: Time zone.

3 bit: Hour.

2 bit: Minute.

1 bit: second.

0 bit: Unknown. Maybe millisecond, or unused.

So, the following line would give me a year only date picker:

[_yearOnlyDatePicker setDatePickerElements:0x0080];

_yearOnlyPicker is an instance of NSDatePicker.


Here is the result:

How yearOnlyDatePicker looks like in Interface Builder:

In interface builder.

How yearOnlyDatePicker looks like when running the app:

When running the app.

Upvotes: 2

GeneCode
GeneCode

Reputation: 7588

It is easy you don't need to use NSDatePicker. All you have to do is create a range of years you want and use it as datasource for normal picker.

for (int i=1900; i<=currentYear; i++) {
  [_yourDataSourceArr addObject:[NSString stringWithFormat:@"%d",i]];
}

Upvotes: 1

Related Questions