I have used NSDatePickers (without steppers) in the cells of a column in an NSTableView. The date pickers are used to set a duration of time in hours, minutes and seconds. If I highlight one of the controls and use the arrow keys to set the values, the date picker displays some weird behaviour:
Seconds increment by two for every time I press up arrow (whereas it should increment by one for each key press);
Seconds do not decrement when I press down arrow;
Every time I increment and decrement the minute and hour values, the seconds value also increases by one (each key press should only increment the selected value).
You can see this behaviour in the below example.
I have configured the NSDatePicker (result) as follows:
result = [[NSDatePicker alloc] initWithFrame:NSZeroRect];
result.identifier = #"timeCell";
result.tag = row;
[result setBordered:NO];
result.backgroundColor = [NSColor clearColor];
result.datePickerElements = NSHourMinuteSecondDatePickerElementFlag;
result.datePickerStyle = NSTextFieldDatePickerStyle;
result.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
[result setTarget:self];
[result setAction:#selector(timePickerDidChange:)];
Question: Does anyone know why this is happening and how I can fix it? Many thanks for your help.
PS: This question also touches on some weirdness surrounding arrow keys and NSDatePicker. It doesn't offer a solution though.
Related
I created a simple maths based app. The app asks a user 6 multiplication table questions. e.g. Q1 10 x 10
The user enters an answer
The app displays whether the user's answer was correct or incorrect and displays this using the following
IBOutlet NSTextField *CorrectIncorrect;
In a cycle of the app (1 question of 6) CorrectIncorrect is used to display the strings 'correct' or 'incorrect' using this line of code
[CorrectIncorrect setStringValue:receivedAnswer];
[[CorrectIncorrect window] display];
Then as the next question is posed to the user, the either string is cleared using the following code.
[CorrectIncorrect setStringValue:#""];
[[CorrectIncorrect window] display];
Initially, each CorrectIncorrect string was being cleared to quickly, so the user never saw if their answer was 'correct' or 'incorrect'. I therefore used a time delay method to slow the process in order to allow the user to see the display before it was cleared.see below
- (void)TimeDelay
{
startInterval = [NSDate timeIntervalSinceReferenceDate];
stopInterval = [NSDate timeIntervalSinceReferenceDate];
while ((stopInterval - startInterval) <= 1)
{
stopInterval = [NSDate timeIntervalSinceReferenceDate];
}
}
This worked fine in Xcode 5. Does not work in Xcode 7.3.1. Any advice appreciated.
Few things:
1) Time interval is in seconds, so <= 1 really isn't much time, have you tried increasing that time and seeing what it looks like?
2) You should also consider adding a button like "Go to next question". That way you won't need to have a timer
3) If you want to have a timer to reset the string, you should just use Grand Central Dispatch
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[CorrectIncorrect setStringValue:#""];
});
one-ish line, and is more intuitive
I'm tying to display a countdown in my app. The timer works fine but I want it to display the time as 00:00:00. Leading zeroes on single digit integers are not ordinarily displayed (eg. 0:1:15) but I can't figure out how to get them in without resorting to clunky if-statements. Here is the relevant code:
-(void)timerFireMethod: (NSTimer *)timer {
[self setUpTimer];
self.timeLabel.text = [NSString stringWithFormat:#"%lu:%lu:%lu", self.timerParts.hour, self.timerParts.minute, self.timerParts.second];
self.counter--; }
Does anyone know what I can do to have the leading zeroes displayed so 0:1:15 becomes 00:01:15?
You can force to display leading zeros by adding .2.
It displays always two digits, in case of < 10 with a leading zero.
self.timeLabel.text = [NSString stringWithFormat:#"%.2lu:%.2lu:%.2lu", self.timerParts.hour, self.timerParts.minute, self.timerParts.second];
I need to show $value on a Label.
currently it appears as 125000 but i need it to be 125,000.00
thanks in advance to all supporters.
The solution of your problem is NSNumberFormatter
Some code to get you started:
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSLog(#"%#", [currencyFormatter stringFromNumber:[NSNumber numberWithInt:10395209]]);
[currencyFormatter release];
Drag the Number Formatter (found in the object library) object onto the field/label. Change the behavior (be sure your in the attributes inspector for the number formatter) to 'OS X 10.4+ Custom' (that's what it was in Xcode 4.5.2).
In the 'Integer Digits' field, change the minimum to 1 and leave the maximum whatever you need. For the 'Fraction Digits' fields set the minimum and maximum to 2.
Near the top of the field, stick a dollar sign in front of the 'Format (+)' and '(-)' fields.
Check the group separator box then change the primary and secondary grouping fields to 3.
I am totally bewildered using NSNumberFormatter. This should be totally simple but I can't get it to work.
I'd like to set an NSTextField to allow typing decimal numbers, either with a decimal point or without. Here is what I'd think would work:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMinimumFractionDigits:0];
[formatter setMaximumFractionDigits:4];
[formatter setAllowsFloats:YES];
[[timeFlowMultiplierTF cell] setFormatter:formatter];
However, when typing in the textfield, pressing the "period" key for the decimal point doesn't yield one. Typing "3.14" give me "314". Throwing in [formatter setAlwaysShowsDecimalSeparator:YES] will initially format the number correctly, but if I type over it, I once again cannot type the decimal point.
What am I missing here? You would think this would be really simple
I realize this is about 4 years too late, but I just ran into this same nonsense and thought I'd share what the problem is (or could be), for posterity.
It turns out that all of the value accessors of NSTextField (-objectValue, -stringValue, -doubleValue, and so on) all end up calling -validateEditing. -validateEditing, in turn, uses the attached NSFormatter to convert the edited text into an object value, and then resets the text in the field with the reformatted value.
So if you have any code that watches the field as the user edits it and you "peek" at the value in the field, you are inadvertently reformatting and resetting the text in the text field.
It's not that the text field won't let you type a period; it's that is the text field already has "3" in it and when you type a period the text changes to "3.". If you then have an action/notification/delegate method that runs whenever something in the field changes, and you call any of the -typeValue methods, the "3." get formatted as "3" and it updates the cell, erasing the period you just typed.
My hack was to avoid the -typeValue methods and peek into the NSText object to get the edited text directly, without triggering -validateEditing:
// some method that runs every time the field changes...
NSTextField* valueField = self.valueField;
NSNumberFormatter* fieldFormatter = valueField.formatter;
NSText* fieldEditor = valueField.currentEditor;
id newValue = ( fieldEditor!=nil ? [fieldFormatter numberFromString:fieldEditor.string] : valueField.objectValue );
Thanks to and following on from #James Bucanek's answer: here is a Swift implementation that I've used when I was over-riding controlTextDidChange delegation method which unblocked the user from typing a decimal point. It also updates the enabled flag of a button on the interface according to if there's a valid (i.e > zero and non-zero length string) entry:
override func controlTextDidChange(notification: NSNotification) {
if let formatter: NSNumberFormatter? = self.user_textfield.formatter as? NSNumberFormatter {
if let field_editor: NSText = self.user_textfield.currentEditor() {
if let new_value: Float? = formatter!.numberFromString(field_editor.string!)?.floatValue {
self.my_button_out.enabled = new_value > 0.0
} else {
self.my_button_out.enabled = false
}
}
}
}
I have got two timevalues in the format: %H%M%S (E.G.161500)
These values are text-based integers.
Is there a simple function in Cocoa that calculates the difference between these two integers using a 60 seconds and minutes scale?
So if
time 1 = 161500
time 2 = 171500
timedifference = 003000
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"HHmmss"];
NSDate *date1 = [dateFormatter dateFromString:#"161500"];
NSDate *date2 = [dateFormatter dateFromString:#"171500"];
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // diff = 3600.0
The class for manipulating dates is NSDate. The method for getting time intervals is -timeIntervalSinceDate:. The result is a NSTimeInterval value, which is a double representing the interval in seconds.
You can create a NSDate object from a NSString with +dateWithString:, provided that your date is formatted as 2001-03-24 10:45:32 +0600.
try this code.
- (NSTimeInterval)intervalBetweenDate:(NSDate *)dt1 andDate:(NSDate *)dt2 {
NSTimeInterval interval = [dt2 timeIntervalSinceDate:dt1];
NSLog(#"%f",interval);
return interval;
}
I would create an NSFormatter subclass to parse time values in that format from input data (you can put one on a text field to automatically convert user input, or use it to parse from a data source in code). Have it return the combined number of seconds as an NSTimeInterval (double representing seconds) wrapped in an NSNumber. From there it's easy to subtract the difference, and display it using the same NSFormatter class you created. In both parsing and displaying values, you're the one responsible to write code converting from seconds to hours:minutes:seconds or whatever format you like. You could also convert these values to an NSDate like mouviciel mentioned, if it makes sense for your application. Just keep in mind you're always going to be storing the time difference from a reference date, usually Jan 1st 1970 (NSDate has methods to do this for you).