NSDate crash with successive actions - ios

I have the following code below that is meant to change a class var called "today" forward or backward by one day. It will work one time but then after that it crashes. It will do the same no matter if I press the left button or right button. What am I doing wrong?
the var today is a class var initiated as .. today = [NSDate date]
Here is the method that crashes:
(IBAction)changeDateByOne:(id)sender{
NSDate *newDay;
NSDate *currentDay = today;
NSTimeInterval secondsPerDay = 24 * 60 * 60;
if(sender == leftButton){
newDay = [currentDay addTimeInterval:-secondsPerDay];
}else if(sender == rightButton) {
newDay = [currentDay addTimeInterval: secondsPerDay];
}
today = newDay;
}

Not only do you need to retain the date created, but you also need to release the existing value held by "today," otherwise you'll leak the old reference.
When initializing the instance, use:
today = [[NSDate date] retain];
I would change the last line to:
[today release];
today = [newDay retain];
And finally, in your dealloc method, add:
[today release];
before calling [super dealloc];

You need to read the memory management documentation. That’s here:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
If you’re adding or subtracting days, you might want to read this which is an alternative way of doing the same thing:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendricalCalculations.html#//apple_ref/doc/uid/TP40007836-SW1
Lastly, if something crashes, it’s often helpful to look at the back traces (and include them in your questions if you can’t figure it out for yourself). Memory management bugs are usually the problem if you see objc_msgSend (or one of its companions) in the trace.

Maybe you need to say
today = [[NSDate date] retain]

I think you need to retain the newDay object returned from the addTimeInterval method. You may also need to release today before you do the assignment at the end.

Related

How to display alert once a day

I'm trying to figure out how I can make an alert popup once the user has reached their goal. However, I only want it to show once a day after it's been triggered. Apologies in advance. if my logic is off with tackling this issue.
// Check to see if hydration goal has been reached
if (waterCups >= dailyHydrationGoal) {
// User has reached goal
if (alert has not been fired yet today) {
// alert pop up you reached your goal!
}
}
How would I go about ensuring it only launches once per day?
You can use isDateInToday: method to check whether the given date is in “today.”
NSDate *lastAlertDate = (NSDate *)[[NSUserDefaults standardUserDefaults] objectForKey:#"lastAlertDate"];
if(![[NSCalendar currentCalendar] isDateInToday:lastAlertDate]){
//Show alert
NSDate *today= [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:#"lastAlertDate"];
}
Do you have a persistence store? (NSUserDefaults, core data etc...)
You can store a time stamp (NSDate) of the last time an alert was shown then check if the last time it was shown is today. How to determine if an NSDate is today?
If an alert has not been shown today, pop an alert and record a new time stamp.

How to check heap memory using instruments in Xcode?

I am trying to analyse the leaks using instruments in Xcode. Here is a sample code I am trying with.
+(NSString *) getUniqueFileName
{
NSDate *time = [NSDate date];
NSDateFormatter* df = [NSDateFormatter new];
[df setDateFormat:#"MMddyyyyhhmmssSSS"];
NSString *timeString = [df stringFromDate:time];
NSString *fileName = [NSString stringWithFormat:#"%#", timeString ];
//[time release];
// [df release];
// [timeString release];
return fileName ;
}
I am using this method every time to generate a filename whenever I capture a photo. All variable are local to his method. If I try to release time, df, timestring, after getting filename, I am getting message sent to deallocated instance. I was sure that if I don't release these variables, memory will be leaking. I tried with instruments and got the following result, and here it is.
Now my question is what is meaning of red color highlighted row with 79.6%? And 20.4% with yellow color row highlighted? Red in general would be dangerous. but what % shows? How it is getting calculated? and when I check call tree, I will get a column named "Leaks" for perticular methods and will contains 100, 234, 560, 2345, some number. What does this number speak about. Help me out. Will be thankful if anyone can provide me good links for understand about instruments.
To explain the percentages in your screenshot, 79.6% of the leaked memory allocated in getUniqueFileName: was allocated in the red line of code. 20.4% of the leaked memory allocated in getUniqueFileName: was allocated in the yellow line of code. Red indicates a high percentage. It may or may not be dangerous.
To explain the Leaks column, it tells you the number of leaks in the method and any functions that method calls. It does not necessarily mean there are that many leaks in the method itself. For example, Cocoa and Cocoa Touch apps start with a main() function. If the main() function has the value 100 in the Leaks column, it means the app has 100 memory leaks, not that main() has 100 leaks.
If you use ARC, disable it to your class, when leaks are creating - now you can release your variables:
Or you can try create your date formatter like this:
NSDateFormatter *df = [[NSDateFormatter alloc] init];

IOS Setting Viewcontroller property bad access error

I am trying to set the property of a child view controller (DateViewController) from the parent and getting a bad access error the second time I do so. Here is the code. This is the DateViewController.h. The problem lies with the selectedDate property:
#import <UIKit/UIKit.h>
#protocol DateViewDelegate <NSObject>
-(void) dateViewControllerDismissed:(NSDate *)selectedDate;
#end
#interface DateViewController : UIViewController {
IBOutlet UIDatePicker *dateReceipt;
id myDelegate;
}
-(IBAction)btnDone;
#property(nonatomic,assign)NSDate *selectedDate;
#property(nonatomic,assign)id<DateViewDelegate> myDelegate;
#end
Inside DateViewController.m, I do synthesize selectedDate. Now in the parent view controller (ComdataIOSViewController.m) I set the selectedDate property of the DateViewController to the variable receiptDate which is declared as an NSDate * in the #interface section of ComdataIOSViewController.h. This is a snippet of ComdataIOSViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
receiptDate = [NSDate date];
}
-(IBAction)btnSetDate {
dlgDate=[[DateViewController alloc] initWithNibName:nil bundle:nil];
dlgDate.selectedDate = receiptDate;
dlgDate.myDelegate = self;
[self presentModalViewController:dlgDate animated:true];
[dlgDate release];
}
-(void) dateViewControllerDismissed:(NSDate *)selectedDate
{
NSDateFormatter *dateFormat = [[[NSDateFormatter alloc] init] autorelease];
[dateFormat setDateStyle:NSDateFormatterShortStyle];
receiptDate = selectedDate;
dateString = [dateFormat stringFromDate:receiptDate];
lblDate.text = dateString;
}
So the first time I click the set date button on the parent controller, the DateViewController appears, I pick the date from the datepicker control, and the controller is dismissed. In the parent view controller, dateViewControllerDismissed gets called and I set the receiptDate to the selectedDate parameter. The next time I click the date button, I get a bad access error where I set the DateViewController's selectedDate property to the receiptDate. I'm assuming this is some sort of memory issue that I'm not handling correctly. IOS programming is still new to me.
I have found several problems in your code which could lead your application to crash. Actually they are memory management problem.
Assigning autoreleased object to receiptDate:
receiptDate = [NSDate date];
when you will try to use this value later it will cause app crash because memory where receiptDate point could be already released. You could fix it by retaining the value:
receiptDate = [[NSDate date] retain];
and releasing in dealloc or anywhere you are changing it (I dont know how it is declared. It should be retain property).
You are assigning NSDate without retaining it:
receiptDate = selectedDate;
you could fix it by retaining:
receiptDate = [selectedDate retain];
I am sorry because I could not write all aspects of memory management in objective-C. It is better to use ARC if you don't know iOS memory managent well.
You could find a lot of useful information in this two guides from Apple: Advanced Memory Management Programming Guide and Memory Management Programming Guide for Core Foundation
Your property is never retained. What I would suggest to do would be to change the assign to retain in your property declaration. That'll solve your problem and you won't have to call retain everywhere you set selectedDate. The property will do that for you.
If you're not using ARC, don't forget to set the property to nil in your dealloc method, like so:
self.selectedDate = nil;
Note that I use self.selectedDate. It's important so that selectedDate is accessed as a property, not a variable.

UILocalNotification show countdown timer on startup or viewdidload

I'm working on app that sets an UILocalNotification. This is the first time I use it and I'd like to have some explanations to use it efficiently and in the best way.
Which is the bast way to countdown to the time of notification expiration? I'd like to show to the user an UILabel with the missing time, this UILabel updates every second and when I reopen my app it must show the timer.
I've done this in this way:
When I reopen my app or the recall the view that has to show the timer I check if there is a UILocalNotification with the userInfo I've setted previously then I subtract to its NSDate
the current time so I get the difference, and update the UILabel. I know it shows time in seconds but if this procedure it's good I will convert it into time.
Is there any best way to do this?
Here is my code:
UILocalNotification *countDownNotificationSetted;
NSArray *scheduledNotificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i = 0; i<[scheduledNotificationArray count]; i++)
if ([[[[scheduledNotificationArray objectAtIndex:i] userInfo] objectForKey:#"ID"] isEqualToString:#"ParkNotification"]) {
countDownNotificationSetted = [scheduledNotificationArray objectAtIndex:i];
break;
}
NSDate *expringDate = [countDownNotificationSetted fireDate];
NSTimeInterval timeLeftToNotification = [expringDate timeIntervalSinceNow];
if(timeLeftToNotification == 0){
[countDownTimer invalidate];
}
datePicker.countDownDuration = timeLeftToNotification;
_countDownLabel.text = [NSString stringWithFormat:#"%.0f", timeLeftToNotification];
NSLog(#"%.0f", timeLeftToNotification);
I think it would be better if you would update your label with a timer as you already do , when you close the app, store that time locally in a file or user defaults and when the app launches again read from that file the time. Or if you want the time passed since the first openning of the app, just write the time in appDidFinishLaunching and get it from there every time . I don't see the benefit of the local notification here.
Hope this helps.
Cheers!

Local variables in dispatch queue call on iOS cause intermittent crashes

I have an app that does some background processing... to update the progress bar not he main thread I call a method using:
dispatch_async(dispatch_get_main_queue(),^{
[self updateProgress];
});
I get EXEC_BAD_ACCESS on this line:
int secs=[nowDate timeIntervalSinceDate:startTransmitDate];
Heres the method:
-(void)updateProgress
{
[mainProgressBar setProgress:((float)dataOffset/(float)totalToSend)];
NSDate *nowDate=[NSDate date];
int secs=[nowDate timeIntervalSinceDate:startTransmitDate];
if(secs>0){
float bps=(float)dataOffset/(float)secs*(float)8.0;
bps=bps/(float)1024.0; // k
bps=bps/(float)1024.0; // M
if(bpsLabelText){
speedLabel.text=nil;
[bpsLabelText release];
bpsLabelText=nil;
}
bpsLabelText=[NSString stringWithFormat:#"%0.1fMb/s",bps];
[bpsLabelText retain];
speedLabel.text=bpsLabelText;
}
}
StartTransmitDate is declared in the class implementation... and set elsewhere:
startTransmitDate=[NSDate date];
[startTransmitDate retain];
What am I missing here?
How startTransmitDate is initialized? If it is not retained anywhere did you initialized it with __block to retain it until the block stop using it?
Could you be missing the nowDate declaration?
NSDate *nowDate = [NSDate date]
Here's a weird idea. Try declaring all of your local instance variables without initializers at the very top of the block, then initialize them only after all instance variables have been declared. If the behavior changes, you may have found a bug!

Resources