How to show year only in NSDatePicker - objective-c

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!

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:
How yearOnlyDatePicker looks like when running the app:

-[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.

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

Related

Linking Text to an Integer Objective C

The goal of this post is to find a more efficient way to create this method. Right now, as I start adding more and more values, I'm going to have a very messy and confusing app. Any help is appreciated!
I am making a workout app and assign an integer value to each workout. For example:
Where the number is exersiceInt:
01 is High Knees
02 is Jumping Jacks
03 is Jog in Place
etc.
I am making it so there is a feature to randomize the workout. To do this I am using this code:
-(IBAction) setWorkoutIntervals {
exerciseInt01 = 1 + (rand() %3);
exerciseInt02 = 1 + (rand() %3);
exerciseInt03 = 1 + (rand() %3);
}
So basically the workout intervals will first be a random workout (between high knees, jumping jacks, and jog in place). What I want to do is make a universal that defines the following so I don't have to continuously hard code everything.
Right now I have:
-(void) setLabelText {
if (exerciseInt01 == 1) {
exercise01Label.text = [NSString stringWithFormat:#"High Knees"];
}
if (exerciseInt01 == 2) {
exercise01Label.text = [NSString stringWithFormat:#"Jumping Jacks"];
}
if (exerciseInt01 == 3) {
exercise01Label.text = [NSString stringWithFormat:#"Jog in Place"];
}
}
I can already tell this about to get really messy once I start specifying images for each workout and start adding workouts. Additionally, my plan was to put the same code for exercise02Label, exercise03Label, etc. which would become extremely redundant and probably unnecessary.
What I'm thinking would be perfect if there would be someway to say
exercise01Label.text = exercise01Int; (I want to to say that the Label's text equals Jumping Jacks based on the current integer value)
How can I make it so I only have to state everything once and make the code less messy and less lengthy?
Three things for you to explore to make your code easier:
1. Count from zero
A number of things can be easier if you count from zero. A simple example is if your first exercise was numbered 0 then your random calculation would just be rand() % 3 (BTW look up uniform random number, there are much better ways to get a random number).
2. Learn about enumerations
An enumeration is a type with a set of named literal values. In (Objective-)C you can also think of them as just a collection of named integer values. For example you might declare:
typedef enum
{
HighKnees,
JumpingJacks,
JogInPlace,
ExerciseKindCount
} ExerciseCount;
Which declares ExerciseCount as a new type with 4 values. Each of these is equivalent to an integer, here HighKnees is equivalent to 0 and ExerciseKindCount to 3 - this should make you think of the first thing, count from zero...
3. Discover arrays
An array is an ordered collection of items where each item has an index - which is usually an integer or enumeration value. In (Objective-)C there are two basic kinds of arrays: C-style and object-style represented by NSArray and NSMutableArray. For example here is a simple C-style array:
NSString *gExerciseLabels[ExerciseKindCount] =
{ #"High Knees",
#"Jumping Jacks",
#"Jog in Place"
}
You've probably guessed by now, the first item of the above array has index 0, back to counting from zero...
Exploring these three things should quickly show you ways to simplify your code. Later you may wish to explore structures and objects.
HTH
A simple way to start is by putting the exercise names in an array. Then you can access the names by index. eg - exerciseNames[exerciseNumber]. You can also make the list of exercises in an array (of integers). So you would get; exerciseNames[exerciseTable[i]]; for example. Eventually you will want an object to define an exercise so that you can include images, videos, counts, durations etc.

If statement to json value

I´m trying to do an If statement from my viewcontroller to my weathercondition.m in which the web service is gathering weather information. It picks up the json from openweathermap API and shows the correct temperature in my app. However I would like to do an If statement to the temperature - like if it´s below 10 Celcius - a label can write out: "It is cold".
When I do this: newsCondition is from weathercondition.m
if (newsCondition.temperature.floatValue == 0) {
[label1 setText:#"It´s really cold today!"];
The label shows in the app but says "It´s really cold today" even though the temperature isn´t zero. Does anyone know how to write the If statement to compare it to the number parsed from the json?
"floatValue" isn't a property.
Why not change your code to something like:
if ([newsCondition.temperature floatValue] <= 0.0f)
{
[label1 setText:#"it's really cold today!"];
}
else
{
[label1 setText:#""];
}
You'll also see I set the label to be blank if the temperature is greater than 0. That's because table view cells (which is what I suspect you are using here) get recycled when old ones scroll out of view.

How do I show which refinements are available for a word?

The date datatype has a great set of refinements, for example:
t: now
t/second
== 21
t/month
== 4
How do I get a list of the available refinements for a word like t?
Words-of is great for functions, but what to do if your word is holding a non-function?
Well, you could try 'help.
It will let you down, however, for example if you want to find the accessors for time! values.
You could also try accessing via numbers, if all you want is to see what's available:
>> x: now/precise
== 15-Jan-2015/16:18:39.609-5:00
>> x/1
== 2015
>> x/9
== 15-Jan-2015/21:18:39.609
However, and I myself just found this out, this can also let you down; date! values have more than 9 accessors, but:
>> x/10
** Script error: cannot access 10 in path x/10
And even if it was complete it would still not answer the question, what are the available refinements?
So, I am here providing another answer: Look it up on SO!
Type Accessor words (and paths)
==== ==========================
date! year month day time zone date weekday julian yearday utc hour minute second
time! hour minute second
pair! x y
gob! offset size size/x size/y alpha
event! offset
The gob! and event! paths are incomplete, since word and value pairs can be added dynamically, but this is a start, and what I've listed here will always be there. (Actually for those two cases, just printing the value gives you the words it recognizes, similar to objects and blocks.)
If it's a function, you can use words-of
words-of :now
== [/year /month /day /time /zone /date /weekday /yearday /precise /utc]
Otherwise the help command is the best option.

Quartz Composer Objective C compare previous with current input

I'm trying to build something that will only fire a command once per keyboard input (as opposed to every frame like QC does natively). In order to do so, I'm trying to listen in on the keyboard inputs (via Freeboard) and compare the current input versus a previous version.
What seems to be happening is the previous version is getting wiped every time the patch executes, so my conditional to compare strings is failing every time. Here's some code to make it a bit clearer:
- (BOOL)execute:(id <QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary *)arguments
{
self.outputPrevious=previousCharacter;
if ([self.inputCharacter caseInsensitiveCompare:previousCharacter]){
self.outputText=#"SAME";
}
else {
self.outputText=#"CHANGE";
}
previousCharacter = [NSString stringWithString:self.inputCharacter];
[previousCharacter retain];
return YES;
}
where self.outputText is the text that tells me the result of the if, self.outputPrevious is telling me what the previous character input was, and self.inputCharacter is the current keyboard input.
previousCharacter is defined in the header and instantiated in -init, so it shouldn't be being reset every time.
I've tried pretty much everything with this, so if you have any ideas or insights, that would be awesome. Thanks!
Figured it out eventually. Full solution can be found here

Cursor position in a UITextView

I am looking for a non private way to find the position of the Cursor or Caret (blinking bar) in a UITextView preferably as a CGPoint.
There may be a question like this already but it does not provide a definitive way for doing it.
And,
I do not mean the NSRange of the selected area.
Just got it in another thread:
Requires iOS 3.2 or later.
CGPoint cursorPosition = [textview caretRectForPosition:textview.selectedTextRange.start].origin;
Remember to check that selectedTextRange is not nil before calling this method. You should also use selectedTextRange.empty to check that it is the cursor position and not the beginning of a text range. So:
if (textview.selectedTextRange.empty) {
// get cursor position and do stuff ...
}
Pixel-Position of Cursor in UITextView
SWIFT 2.1 version:
let cursorPosition = infoTextView.caretRectForPosition( (infoTextView.selectedTextRange?.start)! ).origin
print("cursorPosition:\(cursorPosition)")
There is no such way. Full stop.
The only thing you could do to come close is to in parallel lay out the text using CoreText, there calcualte the text position from a point and apply that on the UITextView. This, however, works with non-0 selections only. In addition CoreText has a different text layout engine, that e.g. supports kerning, which UITextView doesn't. This may result in deviations of the rendered and laid out text and thus give sub-optimal results.
There is absolutely no way to position the caret. This task is even very though if you do use private API. It's just one of the many "just don't" in iOS.
Swift 4 version:
// lets be safe, thus if-let
if let selectedTextRange = textView.selectedTextRange {
let caretPositionRect = textView.caretRect(for: selectedTextRange.start)
let caretOrigin = caretPositionRect.origin
print(">>>>> position rect: \(caretPositionRect), origin: \(caretOrigin)")
}
We simply use textView.selectedTextRange to get selected text range and than textView.caretRect(for:) to get CGRect defining position of the caret.