Memory Leak while using NSDateFormatter - iphone

I have seen many questions/answers on memory leaks in NSDateFormatter, but none seems to help me determine what is causing memory to leak in my app. Here is my code:
- (id)init
{
if ((self = [super init]))
{
items = [[NSMutableArray alloc] init];
events = [[NSMutableArray alloc] init];
buffer = [[NSMutableData alloc] init];
format = [[NSDateFormatter alloc] init];
lastFromDate = #"";
}
return self;
}
- (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
[format setTimeZone:[NSTimeZone systemTimeZone]];
[format setDateFormat:#"MM/dd/yyyy"];
NSString *stringFromDate = [NSString stringWithString:[format stringFromDate:fromDate]];
NSString *stringToDate = [NSString stringWithString:[format stringFromDate:toDate]];
NSLog(#"From date: %#, To date: %#", stringFromDate, stringToDate);
[self didDatesChange:stringFromDate];
if (dataReady) {
[callback loadedDataSource:self];
return;
}
callback = delegate;
[self retrieveEventData:stringFromDate to:stringToDate];
}
- (void)dealloc
{
[items release];
[events release];
[buffer release];
[lastFromDate release];
[format release];
[super dealloc];
}
When I run "Profile" -> "Leaks", I get a memory leak every time the function is called on line
NSString *stringFromDate = [NSString stringWithString:[format stringFromDate:fromDate]];
Can someone explain what might be going on?
thanks, mike

FYI you can change this:
NSString *stringFromDate = [NSString stringWithString:[format stringFromDate:fromDate]];
to this:
NSString *stringFromDate = [format stringFromDate:fromDate];
stringWithString should return an autoreleased NSString though so I don't believe that is the source of your leak. It looks like there is no leak in your code to me.

you just use bellow method for get string from date its work properly......
-(NSString *)StringFromDate:(NSDate *)DateLocal{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM/dd/yyyy"];
NSString *dateString = [dateFormat stringFromDate:DateLocal];
NSLog(#"Date is HERE =====>> %#",dateString);
return dateString;
}
after when you want to get date string just use like bellow....
NSString *stringFromDate = [self stringFromDate:fromDate]];
[stringfromdate retain];
NSString *stringToDate = [self stringFromDate:toDate]];
[stringTodate retain];
and above -(NSString *)StringFromDate:(NSDate *)DateLocal method is must be define in your viewcontroller.m file....
Its work fine....

Related

Memory Leaks while using MFMailComposer

I am trying to send a CSV file through MfMail Composer.Everything works fine but there are lot leaks while using Instruments.I am not able trace out where I went wrong.Here is my code.
-(NSData *)getCSV
{
NSManagedObjectContext *moc = [(ETAppDelegate *)[[UIApplication sharedApplication] delegate]managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc]init]autorelease];
[request setEntity:[NSEntityDescription entityForName:#"Expense" inManagedObjectContext:moc]];
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
NSMutableArray *expensesList = [[[NSMutableArray alloc]init]autorelease];
for(int i = 0;i<[results count];i++){
NSString *category = [[results objectAtIndex:i]valueForKey:#"category"];
NSString *date = [[NSDateFormatter dateFormatterwithMediumStyle]stringFromDate:[[results objectAtIndex:i]valueForKey:#"date"]];
NSString *amount = [NSNumberFormatter localizedStringFromNumber:[[results objectAtIndex:i]valueForKey:#"amount"] numberStyle:NSNumberFormatterCurrencyStyle];
NSString *mailString = [NSString stringWithFormat:#"%#,%#,%#",category,date,amount ];
[expensesList addObject:mailString];
}
NSString *expensesString = [expensesList componentsJoinedByString:#"\n"];
NSData *expensesData = [expensesString dataUsingEncoding:NSUTF8StringEncoding];
return expensesData;
}
-(void)displayComposerSheet
{
NSData *csvFile = [self getCSV];
NSString *csvFileName = #"MyExpenses";
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc]init];
[mailController setSubject:#"List Of Expenses"];
[mailController setMessageBody:#"Expenses" isHTML:NO];
[mailController addAttachmentData:csvFile mimeType:#"text/csv" fileName:csvFileName];
[mailController setMailComposeDelegate:self];
[self presentModalViewController:mailController animated:YES];
[mailController release];
}
I can't say that I see anything in the code you've provided that should cause you to leak. Your leaks are likely taking place elsewhere.
What I do see, however, is the potential to create a lot of autoreleased objects in that loop in -getCSV, and depending on how many iterations you're performing, that could be almost as bad. The way you've written it, I see a date formatter and three strings headed for your main autorelease pool with every iteration. One suggestion is to create a date formatter outside your loop that you can reuse inside it. Another suggestion is to frame the guts of your loop with a local autorelease pool; that will prevent your main autorelease pool from becoming too large.
Apropos of nothing, you should also consider using fast enumeration.
Here's your loop with the suggestions applied:
NSDateFormatter *myDateFormatter = [NSDateFormatter dateFormatterWithMediumStyle];
NSMutableArray *expensesList = [[[NSMutableArray alloc] init] autorelease];
for (id obj in results)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *category = [obj valueForKey:#"category"];
NSString *date = [myDateFormatter stringFromDate:[obj valueForKey:#"date"]];
NSString *amount = [NSNumberFormatter localizedStringFromNumber:[obj valueForKey:#"amount"] numberStyle:NSNumberFormatterCurrencyStyle];
NSString *mailString = [NSString stringWithFormat:#"%#,%#,%#", category, date, amount];
[expensesList addObject:mailString];
[pool release];
}

How to compare an array of NSStrings containing Dates in ascending order

I have an Array in which contains a list of dates represented as strings:
NSMutableArray *objArray=[[NSMutableArray alloc]init];
[objArray addObject:#"18-01-2013 2:51"];
[objArray addObject:#"16-01-2013 5:31"];
[objArray addObject:#"15-01-2013 3:51"];
[objArray addObject:#"17-01-2013 4:41"];
[objArray addObject:#"03-02-2013 3:21"];
[objArray addObject:#"05-01-2013 3:01"];
please tell me how to arrange this array in ascending order by using dates.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"dd-MM-yyyy hh:mm"];
NSComparator compareDates = ^(id string1, id string2)
{
NSDate *date1 = [formatter dateFromString:string1];
NSDate *date2 = [formatter dateFromString:string2];
return [date1 compare:date2];
};
NSSortDescriptor * sortDesc = [[[NSSortDescriptor alloc] initWithKey:#"self" ascending:NO comparator:compareDates]autorelease];
[objArray sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
By using this code i got exact output, thank you for all
we can do another way to get sorting array with dates
NSArray *objArr = [[NSArray alloc]initWithObjects:#"2003/08/02 03:00 ",#"2001/02/04 04:00 ",#"2001/02/04 05:00 ",#"2010/05/01 08:00 ",#"2002/12/02 02:00 ",#"2012/11/05 02:00 ",#"2013/10/01 12:00 ", nil];
NSArray *sortedArray = [objArr sortedArrayUsingComparator:^(id firstObject, id secondObject) {
return [(NSDate * )firstObject compare: (NSDate * ) secondObject];
}];
NSLog(#"sorteed Array %#",sortedArray);
NSSortDescriptor * descLastname = [[NSSortDescriptor alloc] initWithKey:#"active" ascending:YES];
[livevideoparsingarray sortUsingDescriptors:[NSArray arrayWithObjects:descLastname, nil]];
[descLastname release];
videoparsing = [livevideoparsingarray copy];
livevideoparsingarray is my array which I have sort & active is my tag which is in array which I have sort. You change with your requirements.
You can do this by using NSSortDescriptor
NSSortDescriptor* sortOrder = [NSSortDescriptor sortDescriptorWithKey: #"self" ascending: YES];
return [objArray sortedArrayUsingDescriptors: [NSArray arrayWithObject: sortOrder]];
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *str1 = #"18-01-2013";
NSString *str2 = #"16-01-2013";
NSString *str3 = #"15-01-2013";
NSString *str4 = #"17-01-2013";
NSString *str5 = #"03-02-2013";
NSString *str5 = #"05-01-2013";
NSArray *arr = [NSArray arrayWithObjects:str1, str2, str3,str4,str5 nil];
arr = [arr sortedArrayUsingFunction:dateSort context:nil];
NSLog(#"New dates %#",arr);
}
//The date sort function
NSComparisonResult dateSort(NSString *s1, NSString *s2, void *context) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy"];
NSDate *d1 = [formatter dateFromString:s1];
NSDate *d2 = [formatter dateFromString:s2];
return [d1 compare:d2]; // ascending order
// return [d2 compare:d1]; // descending order
}
Try this
NSMutableArray *objArray;
objArray=[[NSMutableArray alloc] init];
[objArray addObject:#"18-01-2013 2:51"];
[objArray addObject:#"16-01-2013 5:31"];
[objArray addObject:#"15-01-2013 3:51"];
[objArray addObject:#"17-01-2013 4:41"];
[objArray addObject:#"03-02-2013 3:21"];
[objArray addObject:#"05-01-2013 3:01"];
NSSortDescriptor *sort_Date=[[NSSortDescriptor alloc] initWithKey:#"self"ascending:NO];
NSLog(#"%#",[[objArray sortedArrayUsingDescriptors:#[sort_Date]] description]);
I got below response
2013-02-06 11:23:35.100[1135:c07]
(
"18-01-2013 2:51",
"17-01-2013 4:41",
"16-01-2013 5:31",
"15-01-2013 3:51",
"05-01-2013 3:01",
"03-02-2013 3:21"
)

Obj-C How to call a method with return?

I have a method with a return value that I want to call from my MainviewController.m. Also, I must pass a value (float) to the method when calling it.
But I'm having trouble with that, I tried to debug and add some breakpoints and NSLog in the method but it appears that the method is not being called, since the debugger doesn't stop at the breakpoint and doesn't print the NSLog. (the final print (calculatorScreen.text...) just print (null))
MainViewController.m
currentNumber = currentNumber *10 + (float)[sender tag];
NSNumber *convertedNumber = [[NSNumber alloc] init];
NSString *nf = [convertedNumber customFormatNumber:currentNumber];
calculatorScreen.text = [NSString stringWithFormat:#"%#",nf]; // it's printing (null) :(
NSNumber+FormatNumber.h
#interface NSNumber (FormatNumber)
-(NSString *) customFormatNumber:(float)n1;
NSNumber+FormatNumber.m
-(NSString *) customFormatNumber:(float)n1
{
NSLog(#" %f" ,n1); // for debug and a breakpoint here
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:0];
NSString *nf = [formatter stringFromNumber:[NSNumber numberWithFloat:n1]];
NSLog(#"Class %#" ,nf); // for debug
return nf;
}
What am I missing here?
[[NSNumber alloc]init] returns nil because you aren't specifying the number value, and nil targeted actions are ignored.
Let me tell you that you are following a long and unnecessary way, I would just write all this way:
NSNumberFormatter* formatter=[NSNumberFormatter new];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:0];
formatter.numberStyle= NSNumberFormatterDecimalStyle;
calculatorScreen.text= [formatter stringFromNumber: #(currentNumber*10.0+[sender tag]) ];
Are you trying to overwrite NSNumber?
For CustomNumber.h
#interface CustomNumber:NSNumber
-(NSString *) customFormatNumber:(float) n1;
For CustomNumber.m
-(NSString *) customFormatNumber:(float)n1
{
NSLog(#" %f" ,n1); // for debug and a breakpoint here
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:0];
NSString *nf = [formatter stringFromNumber:[NSNumber numberWithFloat:n1]];
NSLog(#"Class %#" ,nf); // for debug
[formatter release];
return nf;
}
Then in MainViewController.m
currentNumber = currentNumber *10 + (float)[sender tag];
CustomNumber *convertedNumber = [[CustomNumber alloc] init];
calculatorScreen.text = [convertedNumber customFormatNumber:currentNumber];
OR
In MainViewController.m create the method and then the code will be
currentNumber = currentNumber *10 + (float)[sender tag];
calculatorScreen.text = [self customFormatNumber:currentNumber];

Calendar API changing

http://code.google.com/p/scm-subversion/source/browse/trunk/iPhone/CalendarTest/?r=4#CalendarTest%253Fstate%253Dclosed
I am using the above mentioned Calendar API. In CalendarTestViewController.m class we are getting the date. Now I have declared a global variable nsstring type and I want to use that date into another new class by using global variable. I have tried this a number of times but unable to get the output. If anyone know how can I use the selected date by using Calendar API, then please give me some solution.
Thanks in advance.
CODE
- (void)calendarView:(KLCalendarView *)calendarView tappedTile:(KLTile *)aTile{
NSLog(#"Date Selected is %#",[aTile date]);
str=(NSString *)[aTile date];
}
NSLog(#"str:%#",str);
glbdate1 = (NSString *)[aTile date];
NSLog(#"glbdate1:%#",glbdate1);
}
//I have declared the glbdate1 variable globally in app delegate file and i have made the new class calenderview
//I want to display the date in textfield by using global variable. Here is code in calenderview
-(void)viewWillAppear:(BOOL)animated {
if ([glbdate1 length] != 0)
{
from.text = glbdate1;
}
}
You have to convert the NSDate to NSString as follows,
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-mm-dd HH:mm:ss"];
NSString *dateString=[dateFormatter stringFromDate:date];
Then the same NSString value can be converted to NSDate as,
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-mm-dd HH:mm:ss"];
NSDate *dateFromString=[dateFormatter dateFromString:dateString];
-(BOOL)isDateinEventArray:(NSString*)iDateString{
//NSString *searchText = lblDate.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (ToDo *todoObj in appDelegate.todoArray)
{
NSString *date = todoObj.startDate;
[searchArray addObject:date];
}
if ([searchArray count] > 0) {
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:iDateString
options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyListOfItems addObject:sTemp];
}
[searchArray release];
searchArray = nil;
}
if ([copyListOfItems count] > 0) {
return TRUE;
}else{
return FALSE;
}
}
/*----- Calendar Delegates -----> */
- (void)calendarView:(KLCalendarView *)calendarView tappedTile:(KLTile *)aTile{
NSLog(#"Date Selected is %#",[aTile date]);
// NSString *stringFromDate =
// [[NSString alloc]initWithString:[NSString stringWithFormat:#"%02i-%02i-%i",[aTile.date dayOfMonth],
//
[aTile.date monthOfYear],[aTile.date yearOfCommonEra]]];
NSString *stringFromDate = [[NSString alloc]initWithString:[NSString stringWithFormat:#"%02i-%02i-%02i",[aTile.date yearOfCommonEra],
[aTile.date monthOfYear],[aTile.date dayOfMonth]]];
if([self isDateinEventArray:stringFromDate]){
selectedDate = [aTile date];
eventFoundMsg = #"Events are found on this date.";
eventMsgTag = 1;
}else{
eventFoundMsg = #"No events are found on this date.";
eventMsgTag = 0;
}
[stringFromDate release];
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Event Message"
message:eventFoundMsg
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil]autorelease];
alert.tag = eventMsgTag;
[alert show];
[aTile flash];
/*
if(tile == nil)
tile = aTile;
else
[tile restoreBackgroundColor];
*/
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (eventMsgTag == 1) {
if (buttonIndex == 0)
{
MyToDoView *detailViewController = [[MyToDoView alloc]
initWithNibName:#"MyToDoView" bundle:nil];
detailViewController.searchDate = selectedDate;
NSLog([NSString stringWithFormat:#"%#",detailViewController.searchDate]);
[detailViewController searchDateTableView];
[self.navigationController popViewControllerAnimated:YES];
[detailViewController release];
}
}
}
I hope this can help you....

unrecognized selector sent to instance... Source code link inside

I'm going crazy with this my little app... Please help me!!!
this is the source code of the app: Smoking.zip
It only saves a .dat file with an NSMutableArray.
Now, the first time you will launch the app, try to click the cigarette button sometimes: Everything should working fine.
Ok, now close the app, re-open it, and click again on the button. This time the app will crash with the "unrecognized selector sent to instance 0x5d18d60" error.
I was sure the problem was in saving the data, because when i commented the line "[theData writeToFile:dataFilePath atomically:YES];" in the "saveData" method the error disappeared.
Later i discovered that it appears again if i try to read the data from the NSMutableArray.
Please take a moment to check my project and help me, beacause i'm going crazy about that!!
Here's some code:
#import "SmokingAppDelegate.h"
#import "SmokingViewController.h"
#import "Cig.h"
#implementation SmokingAppDelegate
#synthesize window;
#synthesize viewController, dataFilePath, smokeArray;
#pragma mark -
#pragma mark Application lifecycle
- (id) init {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"a.dat"];
[self setDataFilePath:path];
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:dataFilePath]
) {
//open it and read it
NSLog(#"data file found. reading into memory");
smokeArray = [[NSMutableArray alloc] init];
NSMutableData *theData;
NSKeyedUnarchiver *decoder;
NSMutableArray *tempArray;
theData = [NSData dataWithContentsOfFile:dataFilePath];
decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
tempArray = [decoder decodeObjectForKey:#"smokeArray"];
[self setSmokeArray:tempArray];
[decoder finishDecoding];
[decoder release];
} else {
NSLog(#"no file found. creating empty array");
smokeArray = [[NSMutableArray alloc] init];
[smokeArray insertObject:[[NSNumber alloc] initWithInt:0] atIndex:0];
}
// [self logArrayContents];
return self;
}
- (void) logArrayContents {
for(int j = 1; j < [smokeArray count]; j++) {
int f = [[[smokeArray objectAtIndex:j] num] intValue];
NSLog(#"%i. - %d", j, f);
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
-(void) saveData {
NSMutableData *theData;
NSKeyedArchiver *encoder;
theData = [NSMutableData data];
encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
[encoder encodeObject:smokeArray forKey:#"smokeArray"];
[encoder finishEncoding];
[theData writeToFile:dataFilePath atomically:YES];
[encoder release];
NSLog(#"Saved");
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[viewController release];
[window release];
[dataFilePath release];
[smokeArray release];
[super dealloc];
}
#end
#import "SmokingViewController.h"
#import "SmokingAppDelegate.h"
#import "Cig.h"
#implementation SmokingViewController
#synthesize label;
- (void)viewDidLoad {
[super viewDidLoad];
SmokingAppDelegate *mainDelegate = (SmokingAppDelegate *)[[UIApplication sharedApplication] delegate];
//controlla se il giorno รจ lo stesso rispetto a quello dell'ultima sigaretta fumata
if ([mainDelegate.smokeArray count] > 1) {
Cig *oldCig = [mainDelegate.smokeArray lastObject];
NSArray *tempArray = [self quando];
if ( [[tempArray objectAtIndex:0] intValue]==[[oldCig.dat objectAtIndex:0] intValue]
&& [[tempArray objectAtIndex:1] intValue]==[[oldCig.dat objectAtIndex:1] intValue]
&& [[tempArray objectAtIndex:2] intValue]==[[oldCig.dat objectAtIndex:2] intValue]
) {
N = [oldCig.num intValue];
}
else {
N = 0;
}
[oldCig release];
[tempArray release];
}
//scrive quante sigarette si sono fumate oggi
label.text = [NSString stringWithFormat: #"Today you smoked %d cigarettes",N];
}
- (IBAction) smoke:(UIButton * ) button {
SmokingAppDelegate *mainDelegate = (SmokingAppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"L'array contiene %d sigarette", [mainDelegate.smokeArray count]-1);
N += 1;
[self addNewCigToArray];
[mainDelegate logArrayContents];
[mainDelegate saveData];
label.text = [NSString stringWithFormat: #"Today you smoked %d cigarettes",N];
}
- (void) addNewCigToArray {
//NSLog(#"new cigarette smoked");
SmokingAppDelegate *mainDelegate = (SmokingAppDelegate *)[[UIApplication sharedApplication] delegate];
Cig *newCig = [[Cig alloc] init];
[newCig setDat:[self quando]];
[newCig setNum:[[NSNumber alloc] initWithInt:N]];
[mainDelegate.smokeArray addObject:newCig];
[newCig release];
//[mainDelegate logArrayContents];
}
- (NSArray *) quando {
NSDateFormatter *timeFormat = [[NSDateFormatter alloc] init];
// 0 - Year
[timeFormat setDateFormat:#"YYYY"];
NSString *year = [timeFormat stringFromDate:[NSDate date]];
// 1 - Month
[timeFormat setDateFormat:#"MM"];
NSString *month = [timeFormat stringFromDate:[NSDate date]];
// 2 - Day
[timeFormat setDateFormat:#"dd"];
NSString *day = [timeFormat stringFromDate:[NSDate date]];
// 3 - Hour
[timeFormat setDateFormat:#"HH"];
NSString *hour = [timeFormat stringFromDate:[NSDate date]];
// 4 - Minute
[timeFormat setDateFormat:#"mm"];
NSString *min = [timeFormat stringFromDate:[NSDate date]];
// 5 - Second
[timeFormat setDateFormat:#"ss"];
NSString *sec = [timeFormat stringFromDate:[NSDate date]];
NSArray *newArray = [[NSArray alloc] initWithObjects:year,month,day,hour,min,sec,nil];
return newArray;
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Okay, I am an iPhone newbie so take my suggestion in stride. You could try creating an NSData object, initializing it with theData, and then calling writeToFile on the new NSData object instead of the NSMutableData object.