iPhone simple method definition and calling the current date/time - objective-c

I'm very new to iPhone development, and I'm trying to write a function which will accept one parameter, and return the current date/month and store it in a variable.
But I'm getting a (null) value with NSLog.
Method:
-(NSString *) getNowDateMonth:(NSString *)type {
NSDate *now = [[NSDate alloc] init];
if (type==#"month") {
NSDateFormatter *monthFormat = [[NSDateFormatter alloc] init];
[monthFormat setDateFormat:#"MM"];
NSString *theMonth = [monthFormat stringFromDate:now];
[monthFormat release];
return theMonth;
} else if (type==#"day") {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd"];
NSString *theDate = [dateFormat stringFromDate:now];
//int setDate = theDate;
[dateFormat release];
return theDate;
}
[now release];
return NULL;
}
Calling the function to get value:
NSString *month = [self getNowDateMonth:#"month"];
NSLog(#"%#", month);
Am I going about this the right way?

First of all, compare the strings using [#"month" isEqualToString:type], because two strings containing the same text ("month") may not be equal by the == operator. == checks if they're the same string object, not strings object with the same contents.
Second of all, you're leaking the date when returning the month or day (not releasing now). You should use [NSDate date]; instead of [[NSDate alloc] init].
To sum up, a suggested better version of this method would be:
-(NSString *) getNowDateMonth:(NSString *)type {
NSDate *now = [NSDate date];
if ([#"month" isEqualToString:type]) {
NSDateFormatter *monthFormat = [[NSDateFormatter alloc] init];
[monthFormat setDateFormat:#"MM"];
NSString *theMonth = [monthFormat stringFromDate:now];
[monthFormat release];
return theMonth;
} else if ([#"day" isEqualToString:type]) {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd"];
NSString *theDate = [dateFormat stringFromDate:now];
[dateFormat release];
return theDate;
} else {
return nil;
}
}
Also, there are a few other points that can be taken into consideration to improve this method:
do not use NSString as type; use an enum
do not allocate NSDateFormatter on each call to the method; instead use a static variable in the method

You want to use NSDateComponents to reliably and easily extract unit information i.e. month, day, week etc from an NSDate.
See Date and Time Programming Guide for Cocoa.
Dates are a deceptively complex programing problem so Cocoa has a fully developed set of classes for dealing with them. However, the learning curve is a bit steep.

Related

Why does this function return the same value regardless of input?

I have a method that formats a date string. I've encountered an issue where it returns only the formatted version of the first NSString I pass to it..
Code:
self.lastUpdatedLabel.text = [self convertTime:lastupdated];
self.expiryDate.text = [self convertTime:expiryDate];
Method
- (NSString *)convertTime:(NSString *)date{
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setDateFormat:#"HH:mm - dd/MM/yyyy"];
[timeFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
date = [timeFormatter stringFromDate:[[NSDate alloc]init] ];
return date;
}
Both lastUpdatedLabel and expiry date are set to the value of expiryDate. Surely the method runs every time it is called, producing a different output as the input is different
It looks like you need to update your code to use your argument, date.
As people have mentioned in comments, you are using the current time, [[NSDate alloc] init] instead of the date that was passed in.
If lastUpdated and expiryDate are NSDates, then this will work.
- (NSString *)convertTime:(NSDate *)date{
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setDateFormat:#"HH:mm - dd/MM/yyyy"];
[timeFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
return [timeFormatter stringFromDate:date];
}
If lastUpdated and expiryDate are NSStrings, which is what it looks like you have, then you need to convert your NSStrings to NSDates, using an NSDateFormatter that understands the format of the NSString that you have ... and then pass that NSDate to the code above to create a properly formatted string as output.

"NSDate not an Objective-C object" error shows when run the application in IOS 7 in real device

NSDate object is working for iPhone, iPad when i ran the application in real devices. But when I run the application in iPad real device than it gives <not an Objective-C object> error. I tried to sort out it. but couldn't.
- (NSString*)getDateFromJSONToStringSaveFormat:(NSString *)dateString
{
NSDate *_Date = [NSDate alloc] init];
NSDate *_Date = [self getDateFromJSON:dateString];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
return [dateFormatter stringFromDate:_Date];
}
- (NSDate*) getDateFromJSON:(NSString *)dateString
{
// Expect date in this format "/Date(1268123281843)/"
int startPos = [dateString rangeOfString:#"("].location+1;
int endPos = [dateString rangeOfString:#")"].location;
NSRange range = NSMakeRange(startPos,endPos-startPos);
unsigned long long milliseconds = [[dateString substringWithRange:range] longLongValue];
NSTimeInterval interval = milliseconds/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
because of this issue i initialize the NSDate object and saw the date value. (NSDate *_Date = [NSDate alloc] init];) in here also gives same error? why is that? anyone faced this error ??
First off you can just remove this line:
NSDate *_Date = [NSDate alloc] init];
Since the next line just redeclares it, also you in the line you should remove you are missing a [.
- (NSString*)getDateFromJSONToStringSaveFormat:(NSString *)dateString
{
// Not needed since the line after it also declares the variable.
//NSDate *_Date = [NSDate alloc] init];
NSDate *_Date = [self getDateFromJSON:dateString];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
return [dateFormatter stringFromDate:_Date];
}

NSString to NSDate is NOT working when called multiple times

I have written this function in a class:
- (NSDate *) convertDate : (NSString *) dateStr{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *dateFrmStr = [[NSDate alloc] init];
dateFrmStr = [dateFormatter dateFromString:dateStr];
return dateFrmStr;
}
I am calling this function in another class like this:
NSString * dateStr1 =#"01-01-1977";
NSString * dateStr2 =#"22-12-1977";
NSString * dateStr3 =#"19-01-1978";
MyClass *data = [[MyClass alloc]init];
NSDate *dateObj1 = [data convertDate:dateStr1];
NSDate *dateObj2 = [data convertDate:dateStr2];
NSDate *dateObj3 = [data convertDate:dateStr3];
NSLog(#" >>> dateObj1 %#",dateObj1);
NSLog(#" >>> dateObj2 %#",dateObj2);
NSLog(#" >>> dateObj3 %#",dateObj3);
When I run this the only first date seems to get converted because the output I get is :
>>> dateObj1 1977-01-01 00:00:00 +0000
There is no error nothing but the programs just stops.
I've tried you're code and for me works very fine( with ARC ), probably you're issue is somewhere else in "MyClass"…
BTW! Why don't you make a "category" on NSDate?
Something like this :
NSDate + ConvertDate.h
#interface NSDate (ConvertDate)
+(NSDate *) convertDateFromString : (NSString *)dateString;
#end
NSDate + ConvertDate.m
#implementation NSDate (ConvertDate)
+(NSDate *)convertDateFromString:(NSString *)dateString{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
return [dateFormatter dateFromString:dateString];
}
#end
Yes it looks like your code, the only differences are that you don't need to allocate an instance of "MyClass" to use the
"convertDateFromString" method because you're using a class method.'
could it be
NSString * dateStr2 =#"22-12-1977";
that NSDate thinks 22 as the month??? maybe try 12-22-1977 instead?? i usually use NSDateFormatter to convert to string or date..

NSMutableDictionary losing object

I'm trying to store arrays of objects in an Mutable Dictionary, but it seems like the dictionary is losing some of my arrays (or maybe the arrays are losing the data?).
Anyways, here's where I'm at:
- (NSDictionary *)getTicketsByDay:(NSArray *)tickets {
// take an array of tickets and return a dictionary with dates (given by
// NSDateFormatterShortStyle) as keys and arrays of tickets as the values
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
// get NSDate object without time (only month, day, year)
unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSMutableDictionary *datesDict = [[NSMutableDictionary alloc] init];
for (Ticket *ticket in tickets) {
NSDateComponents *ticketDateNoTimeComponents = [calendar components:flags fromDate:[ticket createdAt]];
NSDate *ticketDateNoTime = [calendar dateFromComponents:ticketDateNoTimeComponents];
NSString *dateString = [formatter stringFromDate:ticketDateNoTime];
NSMutableArray *ticketArray = [datesDict objectForKey:dateString];
NSLog(#"%lu", [ticketArray count]);
if (ticketArray == nil) {
NSLog(#"it's here: %#", dateString);
ticketArray = [[NSMutableArray alloc] init];
}
[ticketArray addObject:ticket];
NSLog(#"%lu", [ticketArray count]);
[datesDict setObject:ticketArray forKey:dateString];
}
return datesDict;
}
But then on the console, at random places (although the same places every time), I get something like
41
41
42
0
it's here: 6/29/12
1
even though the key for the previous objects was also "6/29/12". I've also had it print all the keys in the dictionary and there is only 1.
So somewhere I'm losing my data. What's going on?
I should also mention that I'm on 10.7.4 and using ARC.
The code looks fine to me (if you include suggestions from #ConradShultz)
Note that you don't need to create the ticketDateNoTime since you're using a date format, it will always generate the short format string even if the date contains a time...
So your code could be simplified to:
- (NSDictionary *)getTicketsByDay:(NSArray *)tickets {
// take an array of tickets and return a dictionary with dates (given by
// NSDateFormatterShortStyle) as keys and arrays of tickets as the values
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
NSMutableDictionary *datesDict = [[NSMutableDictionary alloc] init];
for (Ticket *ticket in tickets) {
NSString *dateString = [formatter stringFromDate:[ticket createdAt]];
NSMutableArray *ticketArray = [datesDict objectForKey:dateString];
NSLog(#"%lu", [ticketArray count]);
if (ticketArray == nil) {
NSLog(#"it's here: %#", dateString);
ticketArray = [[NSMutableArray alloc] init];
[datesDict setObject:ticketArray forKey:dateString];
}
[ticketArray addObject:ticket];
NSLog(#"%lu", [ticketArray count]);
}
return datesDict;
}
From the looks of it you'll merely leak memory, and your way of replacing the dictionary entry with itself seems unusual (but I think it should work), but what makes you think you are loosing objects? You are printing the size of your array, which is different for different date strings, so maybe you just got a new date string which made it create a new array for that date?
And about the memory leaking/the unusual code: a more traditional way would be
NSMutableArray *ticketArray = [datesDict objectForKey:dateString];
if (ticketArray == nil) {
ticketArray = [[NSMutableArray alloc] init];
[datesDict setObject:ticketArray forKey:dateString];
[ticketArray release];
}
[ticketArray addObject:ticket];

Getting date info into an array in Objective-C Cocoa framework

I have a function that returns an array to hold date info.
- (NSArray*) getTodayArray
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY"];
NSString *year = [dateFormatter stringFromDate:today];
[dateFormatter setDateFormat:#"MM"];
NSString *month = [dateFormatter stringFromDate:today];
[dateFormatter release];
NSArray *res = [NSArray arrayWithObjects: year, month, nil];
return res;
}
Q1 : Is there any easy way to get all the info (year, month, date, hour, minute ...) in an array not using setDateFormat over and over again?
Q2 : Is there a way so that I can access the content of array using res['year'] or similar? I mean using dictionary?
Q3 : Do I need to release NSArray *res in the caller of this function?
A1: You can do smth like this:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY|MM"];
NSArray* d_arr = [[dateFormatter stringFromDate: [NSDate date]] componentsSeparatedByString: #"|"];
A2: Use NSDictionary:
[NSDictionary dictionaryWithObjectsAndKeys: [d_arr objectAtIndex: 0], #"year", [d_arr objectAtIndex: 1], #"month", nil]
A3: return value is autoreleased. you don't need to release it.
#prosseek
1 - I dont think you have another choice to get the year, month, date, hour, minute ... from NSDate other than this.(I am not sure about it though.)
2 - you can access the objects in the dictionary in the above format but something more like objective-c style. like this
[dateDictionary obectForKey:#"year"];
but you need to define the dictionary in that format
like this
NSDictionary *dateDictionary = [NSDictionary dictionaryWithObjects:year,min,hr,nil forKeys:#"year", #"min", #"hour", nil];
3 - no you dont need to release or autorelease the NSArray in the above method . but i think you need to retain it in the array that is receiving res array if you want to use it after a while.
Why don't you just use a NSArray of NSDates?
You can probably get all of your desired functionality out of its plethora of functions.
A1: You could dump it all out into a string, but then you'd have to parse the string, which wouldn't be any easier.
A2: You could do that if you used an NSDictionary instead of an NSArray.*
A3: No, it's already autoreleased.
* Why don't you write a category for NSDate instead?
NSDate+Convenience.h
#interface NSDate (Convenience)
- (NSInteger)year;
- (NSInteger)month;
#end
NSDate+Convenience.m
#implementation NSDate (Convenience)
- (NSInteger)year {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY"];
NSString *myYear = [dateFormatter stringFromDate:self];
[dateFormatter release];
return myYear;
}
- (NSInteger)month {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM"];
NSString *myMonth = [dateFormatter stringFromDate:self];
[dateFormatter release];
return myMonth;
}
#end
Just #include NSDate+Convenience.h wherever you want to use your handy date and month accessors. All of your NSDate instances will then get them:
NSDate *myDate = [NSDate date];
NSLog(#"%ld %ld", [myDate year], [myDate month]);
No need for loosely-typed NSArrays or NSDictionaries to store this stuff.
(Note you could modify the above code to use a shared NSDateFormatter.)
Q1: Not an array, but you can use -[NSCalendar components:fromDate:] to get an NSDateComponents object. You can use it directly or build an array from it, if that is your preference.
Q2: No, but if you return an NSDateComponents object, then you can use -year, -month, etc methods on it.
Q3: No, you don't need to release it in this method or the caller, unless the caller retains it (which may be desirable).
You're looking for the NSDateComponents class. You'll need to create an NSCalendar object first, then call the components:fromDate: method to get the DateComponents object, after which you can access the object's month, year etc. properties.
Not quite sure what you want here. As it stands, the array cannot be accessed in the manner you describe, though if you want you could always create a dictionary and assign values for keys such as 'month' or 'year'. However, it might just be easier to return the DateComponents object, and access its properties.
No, there is no need to release the NSArray. You constructed it using the NSArray class method, which is already autoreleased.