Ok here is the problem, I have three NSStrings with int values, when the view loads this needs to run:
NSCalendar* gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int uintFlags = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* differenceComponents = [gregorian components:uintFlags
fromDate:quitDate toDate:nowDate options:0];
NSString *hours1 = [NSString stringWithFormat:#"%d",[differenceComponents hour]];
hours = hours1;
NSString *minutes1 = [NSString stringWithFormat:#"%d",[differenceComponents minute]];
minutes = minutes1;
NSString *seconds1 = [NSString stringWithFormat:#"%d",[differenceComponents second]];
seconds = seconds1;
Those NSString now have int values in it, so I can't set int's to static any suggestions?
I wanted to do this way so I won't it...
- (void)updater:(id)sender {
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self
selector:#selector(timer:) userInfo:nil repeats:YES];
}
- (void)timer:(id)sender {
// I get error right here that says (initialize
// element is not a compile-contstant)
static int hour = hours.intValue;
static int minute = minutes.intValue;
static int second = seconds.intValue;
NSString *sec = [NSString stringWithFormat:#"%i",second];
if (seconds1 < 10) {
sec = [NSString stringWithFormat:#"0%i",second];
}
NSString *min = [NSString stringWithFormat:#"%i",minute];
if (minutes1 < 10) {
min = [NSString stringWithFormat:#"0%i",minute];
}
NSString *hours5 = [NSString stringWithFormat:#"%i",hour];
NSString *timerTime = [NSString stringWithFormat:#"%#:%#:%#" ,hours5 ,min ,sec];
label1.text = timerTime;
seconds1 ++;
if (seconds1 > 59) {
seconds1 = 00;
minutes1 ++;
}
if (minutes1 > 59) {
minutes1 = 00;
hours1 ++;
}
}
Why do you want to use static? I don't get the point of making those variables static.
And why using NSString to encapsulate your int values as well?!?? Why not store the int values directly?
Actually you shouldn't either rely of adding the seconds yourself at each execution of the timer method, because an NSTimer can drift, so after some time (quite long time, sure, but still) you can have this drift affect the "seconds" part. Better recompute the timeInterval each time. And why bother adding the leading "0" yourself, when you could use %02i format instead?
Actually your code can be as simple and concise as this:
-(void)timer:(NSTimer*)sender
{
NSTimeInterval elapsedTime = -[quitDate timeIntervalSinceNow];
label1.text = [NSString stringWithFormat:#"%02i:%02i:%02i",
(int)elapsedTime/3600,
((int)elapsedTime/60 ) % 60,
((int)elapsedTime ) % 60];
}
static variable can't be "dynamic". The compiler should know what the value has been assigned before the program run.
just move them to instance variables of said view controller, and set/calculate their values at initialization. done.
The reason why you would want those integers to be static eludes me, still here's a trick that will let you have static (global) data that can be initialized in runtime (dynamically). Just create a class method that manages it:
#interface MyClasss : NSObject
+ (NSDateComponents *)dateComponents;
+ (NSInteger)hours;
+ (NSInteger)minutes;
+ (NSInteger)seconds;
#end
#implementation MyClass
+ (NSDateComponents *)dateComponents
{
NSCalendar* gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int uintFlags = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents* differenceComponents = [gregorian components:uintFlags
fromDate:quitDate toDate:nowDate options:0];
}
+ (NSInteger)hours
{
NSString *hoursText = [NSString stringWithFormat:#"%d",[self dateComponents hour]];
return hoursText.integerValue;
}
+ (NSInteger)minutes
{
NSString *minutesText = [NSString stringWithFormat:#"%d",[self dateComponents minute]];
return minutesText.integerValue;
}
+ (NSInteger)seconds
{
NSString *secondsText = [NSString stringWithFormat:#"%d",[self dateComponents second]];
return secondsText.integerValue;
}
#end
Now you have static data at your disposal which can be accessed without instantiating an object:
NSInteger hours = [MyClass hours];
Related
This question already has answers here:
Calculating the number of days between two dates in Objective-C
(8 answers)
Closed 6 years ago.
Suppose:
1bhk flat 200rupee maintainance
2bhk flat 400rupee maintainance charges
Suppose 1 bhk user pays the amount in a given date.
But if user does not pay the amount in the given date then automatically add 20% extra charge on to the basic amount.
Is it possible to implement this in Objective C?
It's very simple bro. Following code will work for 1BHK user.
float oneBHKCharge=200;
float finalDue=0;
NSString *strDueDate = #"10-02-2017";
NSString *strPaidDate = #"10-02-2017";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *dueDate = [dateFormatter dateFromString:strDueDate];
NSDate *paidDate = [dateFormatter dateFromString:strPaidDate];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [gregorianCalendar components:NSCalendarUnitDay
fromDate:dueDate
toDate:paidDate
options:0];
if (components.day > 0)
{
finalDue = oneBHKCharge + oneBHKCharge*0.2;
}
else
{
finalDue = oneBHKCharge;
}
NSLog(#"%f",finalDue);
Here the code I solved this topic. I stored in the NSUserdefaults the days that count as overdue. An did here the check
- (NSNumber *)invoiceOverDue
{
NSNumber *result;
NSInteger dueDays = [[NSUserDefaults standardUserDefaults] integerForKey:VPPayDue];
if ([[self dueTime] intValue] > dueDays)
{
result = [NSNumber numberWithBool:YES];
}
else {
result = [NSNumber numberWithBool:NO];
}
return result;
}
And here the part in witch I calculate the overdue time.
// DueTime calculation
-(NSNumber *)dueTime
{
// NSTimeInterval secondsPerDay = 24 * 60 * 60;
if ([[self invoiceStatus] intValue] > 1)
{
return [NSNumber numberWithInt:0];
}
else {
NSTimeInterval calculateTime = [[* Insert here the date of your invoice*] timeIntervalSinceNow];
//DLog(#"dueTime bevor / 86400 :%f", calculateTime);
calculateTime /= -86400;
//DLog(#"dueTime :%f", calculateTime);
int returnInt = [ConverterHelper numberRoundUp:calculateTime];
return [NSNumber numberWithInt:returnInt];
}
}
I can't parse this date string: #"2002 0 20", where 0 is January (First month in year is 0, not 1).
Can I use NSDateFormatter to parse this string?
Here http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Parsing_Dates_Times I've read that month should starts on 1.
UPDATE
I need this formatter because I have much data in this format (it is not my data).
I've not found any solution with NSDateFormatter without creating a subclass and overriding format methods.
I don't use NSScan, because it is a too complicated solution, but I think #Andy is right.
I use this code to parse the string:
- (BOOL)getObjectValue:(out __autoreleasing id *)obj forString:(NSString *)string range:
(inout NSRange *)rangep error:(out NSError *__autoreleasing *)error
{
int year = 0;
int month = -1;
int day = -1;
int coutRead = sscanf([string cStringUsingEncoding:NSUTF8StringEncoding], "Date.UTC(%i, %i, %i)", &year, &month, &day);
BOOL result = NO;
if (coutRead == 3)
{
NSDateComponents* components = [[NSDateComponents alloc] init];
components.year = year;
components.month = month + 1;
components.day = day;
*obj = [self.calendar dateFromComponents:components];
result = YES;
}
else
{
obj = 0;
*rangep = NSMakeRange(NSNotFound, 0);
result = NO;
}
return result;
}
Try this:
NSDateFormatter* formatter = [NSDateFormatter new];
formatter.timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
formatter.shortMonthSymbols = #[#"0", #"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", #"9", #"10", #"11"];
formatter.dateFormat = #"yyyy MMM dd"; // Note 3 Ms for "short month" format
NSDate* theDate = [formatter dateFromString:#"2002 0 20"];
Result:
2002-01-20 00:00:00 +0000
No you can't. Parse manually.
At your disposal:
You have NSString that can split string on substrings array using custom delimiter, white space in your case. For example:
-(NSArray*)componentsSeparatedByString:(NSString *)separator
NSScanner that you can use to read integers directly from string.
Documentation is straightforward and comprehensive.
NSNumberFormatter is returning garbage data. The variable of interest is milesString at the bottom. It is rounding to 2 instead of 1.6388. I threw in the debugger info and also added the debugging code for testString and num2. For reference, DistanceFormatter is static, not modified anywhere but this function. I've tried replacing it with a local instance to see if the static object was causing the problem (it wasn't). Another note, I got this error when I wasn't using a roudingMode.
-(NSString *)distanceStringFromLocation:(CLLocation *)location {
if (!DistanceFormatter) {
DistanceFormatter = [NSNumberFormatter alloc];
[DistanceFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
DistanceFormatter.roundingMode = NSNumberFormatterRoundCeiling;
DistanceFormatter.minimumFractionDigits = 0;
DistanceFormatter.maximumFractionDigits = 4;
}
CLLocationDistance distance = [_location distanceFromLocation:location];
distance = distance / 1000;
NSLocale *locale = [NSLocale currentLocale];
BOOL isMetric = [[locale objectForKey:NSLocaleUsesMetricSystem] boolValue];
if (isMetric) {
return [NSString stringWithFormat:#"%# kilometers away", [DistanceFormatter stringFromNumber:[NSNumber numberWithFloat:distance]]];
} else {
CGFloat miles = 0.621371 * distance; //miles = (CGFloat) 1.63877738
NSNumber *num = [NSNumber numberWithFloat:miles]; //num = (__NSCFNumber *)(float)1.63878
NSString *testString = [NSString stringWithFormat:#"%f", miles]; //testString = (__NSCFString *) #"1.63877"
NSNumber *num2 = [DistanceFormatter numberFromString:testString]; //num2 = (NSNumber *)nil
NSString *milesString = [DistanceFormatter stringFromNumber:num]; //milesString = (__NSCFString *)#"2"
return [NSString stringWithFormat:#"%# miles away", milesString];
}
}
You have allocated, but not initialized the date formatter.
DistanceFormatter = [NSNumberFormatter alloc];
should be
DistanceFormatter = [[NSNumberFormatter alloc] init];
With that change you get the result milesString = #"1.6388" .
I have this problem. I have a operation. But if i want to save?
I want to save all (textfield data picker and result in a label)
I have 2 textfield and 1 datapicker + the result in a Label.
this is my M :
#import "ViewController.h"
#import "ResultViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize myLabel;
-(IBAction)calculate:(id)sender{
NSDate *past = _data.date ;
NSDate *now = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSDayCalendarUnit;
NSDateComponents *components = [gregorianCalendar components:unitFlags
fromDate:past
toDate:now
options:0];
int z = [components day];
int a = ([_textField1.text intValue]);
int b = a*([_textField2.text intValue]);
int r = b * z / 20;
myLabel.text = [[NSString alloc] initWithFormat:#"%d", r];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSDate *past = _data.date ;
NSDate *now = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSDayCalendarUnit;
NSDateComponents *components = [gregorianCalendar components:unitFlags
fromDate:past
toDate:now
options:0];
int z = [components day];
int a = ([_textField1.text intValue]);
int b = a*([_textField2.text intValue]);
int r = b * z / 20;
myLabel.text = [[NSString alloc] initWithFormat:#"%d", r];
self.textField1.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"key1"];
self.textField2.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"key2"];
self.myLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"key3"];
self.data = [[NSUserDefaults standardUserDefaults] objectForKey:#"key4"];
[[NSUserDefaults standardUserDefaults]synchronize];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detail"]) {
ResultViewController* destVC = (ResultViewController*)segue.destinationViewController;
destVC.myString = self.myLabel.text;
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:YES];
[[NSUserDefaults standardUserDefaults] setObject:self.textField1.text forKey:#"key1"];
[[NSUserDefaults standardUserDefaults] setObject:self.textField2.text forKey:#"key2"];
[[NSUserDefaults standardUserDefaults] setObject:self.myLabel.text forKey:#"key3"];
[[NSUserDefaults standardUserDefaults] setObject:self.data forKey:#"key4"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
#end
This code is Right?
Thank you....
Couple things.
In your -viewDidLoad, you call -synchronize for some reason. All this does is perform the save function for any events on your user defaults. From what I can see, you don't have any and can skip this call to -synchronize.
One of your logs is showing the value of 'r'. The value is an int value and you should use '%i' to display this correctly. You are performing some calculations to get that value, so you may want that to be a double or something else, but you are currently casting it to an int.
I don't see anything regarding the user defaults that looks out of sorts. So maybe you can specify what exactly is wrong or isn't being done correctly to get some better help.
Yes code looks right.
What is your _data variable type?
If you having trouble saving to NSUser. Try to save self.data.date
One tip : You don't need to synchronize after getting values from NSUserdefautls. Use synchronize after setting values to NSUserdefaults.
I’m trying to make a counter which shows the number of days until we leave on a trip to Europe. It’s only about 70 days (as of today) so I don’t believe that I should have to worry about astronomically large numbers or anything, but I really am stumped - I’ve attached the code that some friends have given me, which don’t work either. Trust me when I say I’ve tried everything I can think of - and before anyone bites my head off, which I have seen done on these forums, yes I did look very extensively at the Apple Documentation, however I’m not 100% sure where to start - I’ve tried NSTimer, NSDate and all their subclasses and methods, but there’s nothing that jumps out immediately.
In terms of what I think I should actually be doing, I think I need to somehow assign an integer value for the “day” today/ now/ the current day, which will change dynamically using the [NSDate date] and then the same for the date that we leave. The countdown is just updating when the method gets called again (I can do this using NSTimer if need be) and the value that is displayed on the countdown is the differnce between these two values.
I don’t especially want to have a flashing kind of thing that updates every second until we leave - personally I think that’s tacky, but if anyone knows how then I’d appreciate it for future reference.
I’ve also done an extensive search of google, and I may simply be using the wrong search terms, but I can’t find anything there either.
Any help is greatly appreciated.
Thank you very much.
Michaeljvdw
- (void)countDownMethod {
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:startDay];
[comps setMonth:startMonth];
[comps setYear:startYear];
[comps setHour:startHour];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
NSLog(#"%#",date);
[gregorian release];
[comps release];
NSTimeInterval diff = [date timeIntervalSinceNow];
int diffInt = diff;
NSString *days = [NSString stringWithFormat:#"%d",diffInt/86400];
day0.text = #"0";
day1.text = #"0";
day2.text = #"0";
NSLog(#"Days Length: %d",days.length);
if(days.length >= 1){
day2.text = [days substringFromIndex:days.length - 1];
if(days.length >= 2){
day1.text = [days substringWithRange:NSMakeRange(days.length - 2, 1)];
if(days.length >= 3){
day0.text = [days substringWithRange:NSMakeRange(days.length - 3, 1)];
}
}
}
NSString *hours = [NSString stringWithFormat:#"%d",(diffInt%86400)/3600];
hour0.text = #"0";
hour1.text = #"0";
NSLog(#"Hours Length: %d",hours.length);
if(hours.length >= 1){
hour1.text = [hours substringFromIndex:hours.length - 1];
if(hours.length >= 2){
hour0.text = [hours substringWithRange:NSMakeRange(hours.length - 2, 1)];
}
}
NSString *minutes = [NSString stringWithFormat:#"%d",((diffInt%86400)%3600)/60];
minute0.text = #"0";
minute1.text = #"0";
NSLog(#"Minutes Length: %d",minutes.length);
if(minutes.length >= 1){
minute1.text = [minutes substringFromIndex:minutes.length - 1];
if(minutes.length >= 2){
minute0.text = [minutes substringWithRange:NSMakeRange(minutes.length - 2, 1)];
}
}
}
If you know the time in seconds between 2 dates (your NSTimeInterval) then you can easily convert that into a string in the format days:hours:mins:secs as follows.
- (NSString*)secsToDaysHoursMinutesSecondsString:(NSTimeInterval)theSeconds {
div_t r1 = div(theSeconds, 60*60*24);
NSInteger theDays = r1.quot;
NSInteger secsLeftFromDays = r1.rem;
div_t r2 = div(secsLeftFromDays, 60*60);
NSInteger theHours = r2.quot;
NSInteger secsLeftFromHours = r2.rem;
div_t r3 = div(secsLeftFromHours, 60);
NSInteger theMins = r3.quot;
NSInteger theSecs = r3.rem;
NSString* days;
if (theDays < 10) { // make it 2 digits
days = [NSString stringWithFormat:#"0%i", theDays];
} else {
days = [NSString stringWithFormat:#"%i", theDays];
}
NSString* hours;
if (theHours < 10) { // make it 2 digits
hours = [NSString stringWithFormat:#"0%i", theHours];
} else {
hours = [NSString stringWithFormat:#"%i", theHours];
}
NSString* mins;
if (theMins < 10) { // make it 2 digits
mins = [NSString stringWithFormat:#"0%i", theMins];
} else {
mins = [NSString stringWithFormat:#"%i", theMins];
}
NSString* secs;
if (theSecs < 10) { // make it 2 digits
secs = [NSString stringWithFormat:#"0%i", theSecs];
} else {
secs = [NSString stringWithFormat:#"%i", theSecs];
}
return [NSString stringWithFormat:#"%#:%#:%#:%#", days, hours, mins,secs];
}
//Another simple way to get the numbers of days difference to a future day from today.
NSTimeInterval todaysDiff = [todayDate timeIntervalSinceNow];
NSTimeInterval futureDiff = [futureDate timeIntervalSinceNow];
NSTimeInterval dateDiff = futureDiff - todaysDiff;
div_t r1 = div(dateDiff, 60*60*24);
NSInteger theDays = r1.quot;
label.text = [NSString stringWithFormat:#"%i", theDays];