why are these methods leaking NSDate objects? - iphone

First one:
+ (NSDate*)convertToUTC:(NSDate*)sourceDate
{
NSTimeZone* currentTimeZone = [NSTimeZone localTimeZone];
NSTimeZone* utcTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"UTC"];
NSInteger currentGMTOffset = [currentTimeZone secondsFromGMTForDate:sourceDate];
NSInteger gmtOffset = [utcTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval gmtInterval = gmtOffset - currentGMTOffset;
return [NSDate dateWithTimeInterval:gmtInterval sinceDate:sourceDate];
}
Yes, I know this next one is strange but my server gives me a whack date format
+(NSDate *)getDateFromString:(NSString *)dtStr
{
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[inputFormatter setLocale:locale];
[locale release];
[inputFormatter setDateFormat:#"MMMM, dd yyyy HH:mm:ss"];
NSDate *formatterDate = [[inputFormatter dateFromString:dtStr] copy];
[inputFormatter release];
return formatterDate;
}

The first one doesn't, but the second one does, because you created a copy and didn't autorelease it. If you don't release it later, it will be leaked.
I don't see why you're even copying the date in the second method. Just cut that out and that will fix the leak.
You really should read (or re-read) the Memory Management Programming Guide for Cocoa, as it seems you need to refine your understanding of the memory-management rules.

Related

Why NSDateFormatter returns NULL on 24h locals with a 12h time setup?

Hi Experts of the world,
I ran into a very weird problem:
I am formatting a string representing time from 00-23 (as returned by a Google service) in the following manner:
(passing in a string of lets say 14, should output either 14:00 or 2:00 PM, depends on user local)
+(NSString *) formatTime: (NSString *)timeToBeFormatted {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"HH"];
NSDate *date = [[NSDate alloc] init];
date = [dateFormat dateFromString:timeToBeFormatted];
// Convert date object to desired output format
[dateFormat setTimeStyle:NSDateFormatterShortStyle];
timeToBeFormatted = [dateFormat stringFromDate:date];
return timeToBeFormatted;
}
Everything works fine in all locals worldwide.
However, ONLY if a user has his TIME format set on 12h in a local where the default is 24h the formatter will return NULL ONLY for vales between 12-23.. Pretty weird i would say!
Example:
before formatter 12
after 12:00 AM
before formatter 13
after (null)
Any ideas why this could happen?
Thanks!
Solved! (inspired by the answers above)..
To solve the issue i am creating a specific Locale, then phrasing the stringToDate using this locale. Then i am creating another Locale with the default users preferences and phrasing the dateBackToString using that locale..
+(NSString *) formatTime: (NSString *)timeToBeFormatted
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
//ADDED//
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormat setLocale:enUSPOSIXLocale];
[dateFormat setDateFormat:#"HH"];
NSDate *date = [[NSDate alloc] init];
date = [dateFormat dateFromString:timeToBeFormatted];
//ADDED//
NSLocale *defualtLocale = [[NSLocale alloc] init];
[dateFormat setLocale:defualtLocale];
[dateFormat setTimeStyle:NSDateFormatterShortStyle];
timeToBeFormatted = [dateFormat stringFromDate:date];
return timeToBeFormatted;
}
I guess its quite costly for older devices but in the era of ARC and strong phones it works ;)
NSDateFormatter uses the current locale and time settings for parsing (and outputting) time. If you want to use a specific time format, set the locale for the date formatter yourself.
dateFormat.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
Also, creating date formatter is expensive, if you call this function often you should cache the date formatter in a static variable.
I was also facing this issue before some time.
Use following code to formate your date as per your need.
+(NSDate *)getGMTDateToView:(NSDate *) availableDate formatter:(NSDateFormatter *)timeFormat {
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[timeFormat setLocale:enUSPOSIXLocale];
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSTimeInterval gmtTimeInterval = [availableDate timeIntervalSinceReferenceDate] + timeZoneOffset;
[timeFormat setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[timeFormat setDateStyle:NSDateFormatterShortStyle];
[timeFormat setTimeStyle:NSDateFormatterShortStyle];
enUSPOSIXLocale = nil;
return [NSDate dateWithTimeIntervalSinceReferenceDate:gmtTimeInterval];
}
I found above code from one of apple's document (I have modified(little bit) it as per my need) but unable to find this link right now.

Not showing appropriate NSDate time in iphone?

I accessing a web service after i parsing that that code i got AiringTime of US EST 2011-10-17T14:00:00Z remaining code i written below
NSString *string = [[dateArray objectAtIndex:0] objectForKey:#"AiringTime"];
NSArray *stringArray1 = [string componentsSeparatedByString:#"T"];
NSString *string1 = [stringArray1 objectAtIndex:1];
NSArray *stringArray2 = [string1 componentsSeparatedByString:#"Z"];
NSString *dateInString = [stringArray2 objectAtIndex:0];
nowDate =[stringArray1 objectAtIndex:0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
NSDate *dateFromString = [formatter dateFromString:dateInString];
[formatter release];
above NSDate *dateFromString given me appropriate output like 14:00 from morning to evening 6:30PM. After evening 6:30PM dateFromString gave mi nil value even though dateInString has an appropriate value?? Why? and How it happen?
I mean,
NSDate *dateFromString = [formatter dateFromString:dateInString];
this line not working, dateFromString gave me nil output.
I wasting my last 3 days evening time due to this strange problem. Please help me.
Thanks in advance.
See here, the example format is exactly the one you are dealing with.
Instead of splitting and manipulating the string yourself, simply do the following:
NSString *string = [[dateArray objectAtIndex:0] objectForKey:#"AiringTime"];
//Time in according to GMT+
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *dateFromString = [formatter dateFromString:string];
[formatter release];
If you are only interested in the time then NSDate is meaningless. What do you want to do with it afterwards?

Time zone added to hour after using nsdateformatter

I'm trying to convert a string date (2011-06-08T08:05:00.000-08:00) into a NSDate using the following code:
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
//Translate 2011-06-08T08:05:00.000-08:00 into 2011-06-08T08:05:00.000-0800
stringDate = [stringDate stringByReplacingOccurrencesOfString:#":" withString:#"" options:0 range:NSMakeRange([aDate length] - 5, 5)];
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ"];
NSDate *dateFromString = [dateFormatter dateFromString:stringDate];
At this point, dateFromString is 2011-06-08 16:05:00 +0000. What I actually wanted was for dateFromString to be 2011-06-08 08:05:00 -0800. What am I doing wrong?
Thanks!
So this will not have a direct answer and will assume that your string format will be the same. What we are going to extract the timezone part (last 5 characters) and then calculate how many seconds we are off from GMT. NSTimeZone has a convenience method timeZoneForSecondsFromGMT: that will help us get what we need. This is what you need to add to the code in the question.
NSString * zoneString = [stringDate substringFromIndex:([stringDate length] - 5)];
NSTimeInterval timeInterval = [[zoneString substringToIndex:3] intValue] * 3600;
timeInterval += [[zoneString substringFromIndex:3] intValue] * 60;
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:timeInterval]];
[formatter setDateFormat:#"yyyy'-'MM'-'dd' 'HH':'mm':'ss ZZZ"];
NSLog(#"%#", [formatter stringFromDate:dateFromString]);
Hopefully this helps you. If you've found a better answer already, let us know.
Original Answer
One thing about the NSDate is that the time returned is always in GMT. You can't change that. You will have to use an NSDateFormatter to print it right. Something like this,
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"PST"]];
[formatter setTimeStyle:NSDateFormatterFullStyle];
[formatter setDateStyle:NSDateFormatterFullStyle];
NSLog(#"%#", [formatter stringFromDate:[NSDate date]]);
So setting the timezone for the formatter that does dateForString: won't help. You will need to create a new one when you want them with a different timezone.

NSDateFormatter causing zombie woes

I've always had some issues getting the infamously picky NSDateFormatter from causing memory instability in my code. I must not grasp how to use it properly. I've looked at tons of sample code and modeled my method after this, but it seems memory issues still plague me. The issues I'm having is that this method is creating a zombie - not too sure how / why. Some insight would be wonderful!!
-(NSString *)getTimeZoneFormatedDate:(int)subtractMinutes TimeZoneOffset:(NSString *)timeZoneOffset
{
float timeZoneOffsetInt = [timeZoneOffset floatValue];
//Calculate the requested UTC time
NSDate *UTCDateTimeNow = [NSDate date];
NSDate *UTCDateTimePast = [UTCDateTimeNow dateByAddingTimeInterval:((subtractMinutes*60)+(timeZoneOffsetInt*60*60))];
//Round the minutes down
NSDateComponents *time = [[NSCalendar currentCalendar]
components:NSHourCalendarUnit | NSMinuteCalendarUnit
fromDate:UTCDateTimePast];
int minutes = [time minute];
float minuteUnit = floorf((float) minutes / 10);
minutes = minuteUnit * 10;
//Format the minutes string
NSString *minuteString;
minuteString = [NSString stringWithFormat:#"%d",minutes];
if ([minuteString length] < 2)
minuteString = [#"0" stringByAppendingString:minuteString];
//Format the rest of the date & time
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
NSDateFormatter *dateFormatter;
dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"yyyy-MM-dd, HH:"];
NSString *yearMonthDayHourString = [dateFormatter stringFromDate:UTCDateTimePast];
//Put the two together and return it!
return [yearMonthDayHourString stringByAppendingString:minuteString];
}
I'm implementing it like so:
NSString *timeZoneText = [self getTimeZoneFormatedDate:minuteModifier*-10 TimeZoneOffset:radarTimeZoneOffset];
If I run my project with the dateformatter commented out and my method just returning:
return #"blah blah";
No issues - everything runs bug free. So, I believe it's safe to assume the issue lies within! Thanks for the help!
I think the problem is that your "NSString *yearMonthDayHourString" is autoreleased string.
You can retain it in your implementation code something like that
self.timeZoneText = blabla if timeZoneText is property with retain
or just [timeZoneText retain]; and release later;
You can try out NSDateFormatter's getObjectValue:forString:range:error: method. Maybe returned NSError provides you a reasonable explanation why it failed.
On the other hand there might be an easier way to get the result:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm:ss"];
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:usLocale];
[usLocale release];
return [dateFormatter stringFromDate:date];

Object sent -autorelease too many times

I have this code that simple returns Today's date as a string formatted:
+(NSString*) getTodayString_YYYY_MM_DD {
NSDate * today = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
return [[formatter stringFromDate:today] autorelease];
}
With instruments I'm not getting a memory leak, but when I Analyze, XCode says:
Object sent -autorelease too many times
If I understand correctly, I have to release manually the formatter as I'm creating it using 'alloc', but I can't release here because I have to return the value, so I add the autorelease.
How I can do it better to improve it ?
thanks,
r.
You are -autoReleasing the NSString, not the formatter.
You don't need an autoRelease since -stringFromDate: is giving you an already autoReleased string.
Here is one way your code can look like:
+(NSString*) getTodayString_YYYY_MM_DD {
NSDate * today = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
NSString *retString = [formatter stringFromDate:today];
[formatter release];
return retString;
}
Given that an NSDate's description is always in the format YYYY-MM-DD HH:MM:SS ±HHMM:
+ (NSString *) getTodayString_YYYY_MM_DD
{
return [[[NSDate date] description] substringToIndex:10];
}
Just throwing it out there. It's probably less efficient than the NSDateFormatter method.