I have two view controllers, both connected via Segue and using Storyboard.
In view controller 1 I have an NSTimer counting up and updating a UILabel.
When I switch to view controller 2 and back to 1 the uilabel is no longer updated.
Here is some code:
headerfile
NSString *timerTicksForCounter;
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateTimerLabel];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateTimerLabel];
}
- (void) startLastConUpdater
{
lastCTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
-(void) updateTimerLabel
{
NSLog(#"timer: %#", timerTicksForCounter);
if (timerTicksForCounter) {
NSLog(#"timer not null");
mainTimerLabel.text = timerTicksForCounter;
}
}
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:stopDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
timerTicksForCounter = [dateFormatter stringFromDate:timerDate];
[self updateTimerLabel];
}
What do you mean it's no longer updated ? Does this mean you lose what was displayed before switching or it doesn't update anymore. If it's not updating anymore it's because you don't start the timer in the appropriate method. You could do something like :
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self startLastConUpdater];
}
This should solve both issues I mentioned above.
Related
I have a uitextlabel that is updated using an nstimer.
When I switch to another view controller (storyboard segue) and back again the text label is no longer updated (returns to default text), even though the timer continues to run.
The timer is writing a value to the uitextlabel which stops working after switching.
NOTE: the updateTimerLabel method continues to output the correct info but the label is not updated.
headerfile
NSString *timerTicksForCounter;
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateTimerLabel];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateTimerLabel];
}
- (void) startLastConUpdater
{
lastCTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
-(void) updateTimerLabel
{
NSLog(#"timer: %#", timerTicksForCounter);
if (timerTicksForCounter) {
NSLog(#"timer not null");
mainTimerLabel.text = timerTicksForCounter;
}
}
- (void)updateTimer
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:stopDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
timerTicksForCounter = [dateFormatter stringFromDate:timerDate];
[self updateTimerLabel];
}
update your textField text in
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateLabel];
}
First Declare
NSTimer * countdownTimer;
NSUInteger remainingTicks;
- (void)viewDidLoad
{
[super viewDidLoad];
remainingTicks = 60;
[self updateLabel];
countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: #selector(handleTimerTick) userInfo: nil repeats: YES];
}
-(void)handleTimerTick
{
remainingTicks--;
[self updateLabel];
if (remainingTicks <= 0) {
[countdownTimer invalidate];
countdownTimer = nil;
}
}
-(void)updateLabel
{
timeLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue];
}
//sent notification
[[NSNotificationCenter defaultCenter] removeObserver:self];
**//Get (Retrive) Notification**
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveTestNotification:)
name:#"TestNotification"
object:nil];
//Get notification method.
- (void) receiveTestNotification:(NSNotification *) notification
{
// [notification name] should always be #"TestNotification"
// unless you use this method for observation of other notifications
// as well.
if ([[notification name] isEqualToString:#"TestNotification"])
NSLog (#"Successfully received the test notification!");
**//Here write your code for update textfield**
}
This question already has an answer here:
Adding pause functionality for NSTimer
(1 answer)
Closed 9 years ago.
In the project I am working on I need to have a stopwatch that will pause and continue. So far All of the basic functions work, but I have not been able to find a way to pause the timer and re-start it. FYI, I have already checked the other postings and they didn't work. Code:
.h:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface Timer : UIViewController <AVAudioRecorderDelegate, AVAudioPlayerDelegate>
{
AVAudioRecorder *recorder;
AVAudioPlayer *player;
}
#property (weak, nonatomic) IBOutlet UIButton *recordPauseButton;
#property (weak, nonatomic) IBOutlet UIButton *stopButton;
#property (weak, nonatomic) IBOutlet UILabel *stopwatchLabel;
-(IBAction)recordPauseTapped:(id)sender;
-(IBAction)stopTapped:(id)sender;
#end
.m:
#import "Timer.h"
#interface SongIdeasRecording ()
#property (strong, nonatomic) NSTimer *stopWatchTimer; // Store the timer that fires after a certain time
#property (strong, nonatomic) NSDate *startDate; // Stores the date of the click on the start button
#end
#implementation Timer
#synthesize stopButton, playButton, recordPauseButton, stopwatchLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)updateTimer
{
// Timer is 1/10 of a second so thats what we add to stopwatch
NSTimeInterval timeInterval = 0.1;
// Create a date formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
// Take the time currently displayed on the stopwatch and add the time interval to it
NSDate *oldDate = [dateFormatter dateFromString:self.stopwatchLabel.text];
NSDate *newDate = [oldDate dateByAddingTimeInterval:timeInterval];
//Get a string representation of the new date
NSString *timeString = [dateFormatter stringFromDate:newDate];
self.stopwatchLabel.text = timeString;
}
- (IBAction)recordPauseTapped:(id)sender {
self.startDate = [NSDate date];
// Create the stop watch timer that fires every 100 ms
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
// Stop the audio player before recording
if (player.playing) {
[player stop];
}
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[recorder record];
[recordPauseButton setTitle:#"Pause" forState:UIControlStateNormal];
} else {
// Pause recording
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
[recorder pause];
[recordPauseButton setTitle:#"Record" forState:UIControlStateNormal];
}
[stopButton setEnabled:YES];
[playButton setEnabled:NO];
}
- (IBAction)stopTapped:(id)sender {
[recorder stop];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive:NO error:nil];
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
- (void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully: (BOOL)flag{
[recordPauseButton setTitle:#"Record" forState:UIControlStateNormal];
[stopButton setEnabled:NO];
[playButton setEnabled:YES];
}
- (IBAction)playTapped:(id)sender {
if (!recorder.recording){
player = [[AVAudioPlayer alloc] initWithContentsOfURL:recorder.url error:nil];
[player setDelegate:self];
[player play];
self.startDate = [NSDate date];
stopwatchLabel.text = #"00:00:00.000";
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
}
- (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
#end
In your case, you are calculating the value of the stopwatch label with the NSDate that the record button was originally pressed. There is no way to pause the timer in this way, as for every time you recalculate the value of the stopwatch label, it will reflect the original date of which the record button was pressed. I would recommend changing this method to something like this:
- (void)updateTimer
{
// Timer is 1/10 of a second so thats what we add to stopwatch
NSTimeInterval timeInterval = 0.1;
// Create a date formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss.SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
// Take the time currently displayed on the stopwatch and add the time interval to it
NSDate *oldDate = [dateFormatter dateFromString:self.stopwatchLabel.text];
NSDate *newDate = [oldDate dateByAddingTimeInterval:timeInterval];
//Get a string representation of the new date and BOOM POW.
NSString *timeString = [dateFormatter stringFromDate:newDate];
self.stopwatchLabel.text = timeString;
}
Have not tested this but I hope it works. I wouldn't be surprised if there were some syntax issues too. Also, make sure the string that is in self.stopwatchLabel.text follows the format to start (Ex. 00:00:00.000).
Try commenting your code inside - (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player.
My guess is that in - (IBAction)recordPauseTapped:(id)sender you're calling [player stop], which triggers - (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag which invalidates your new timer.
- (IBAction)recordPauseTapped:(id)sender {
if ([stopwatchLabel.text isEqual: #"00:00:00.000"]) {
self.startDate = [NSDate date];
// Create the stop watch timer that fires every 100 ms
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
// Stop the audio player before recording
if (player.playing) {
[player stop];
}
if (!recorder.recording) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
// Start recording
[recorder record];
[recordPauseButton setTitle:#"Pause" forState:UIControlStateNormal];
}
}else {
// Pause recording
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
[recorder pause];
[recordPauseButton setTitle:#"Record" forState:UIControlStateNormal];
}
[stopButton setEnabled:YES];
[playButton setEnabled:NO];
}
I have a simple app that has an NSTimer object in the appDelegate to be accessed by all views. The structure of the app is with a UINavigationController. When I fire the NSTimer object, my UILabel is being updated with the correct countdown function, but when I go back to the rootViewController and back to the countdown timer view, my UILabel is being updated with the current countdown time, but no subsequent updates to the UILabel happen. What am I missing? I have done research on making sure the UILabel object is not nil, that I call the function on the viewDidAppear method, and nothing seems to work! Here is the code:
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
}
#property (nonatomic, retain) NSTimer *countdownTimer;
AppDelegate.m
#implementation AppDelegate
#synthesize countdownTimer;
CountdownTimerViewController.h
#import "AppDelegate.h"
enter code here
#interface CountdownTimerViewController : UIViewController {
enter code here
AppDelegate *appdelegate;
}
#property (strong, nonatomic) IBOutlet UILabel *labelCountdownTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStartTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStopTimer;
- (IBAction)startTimer:(id)sender;
- (IBAction)stopTimer:(id)sender;
CountdownTimerViewController.m
#implementation CountdownTimerViewController
#synthesize labelCountdownTimer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Instatiating Appdelegate
if(!appdelegate)
appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (void) viewDidAppear:(BOOL)animated {
if ([appdelegate.countdownTimer isValid]) {
[self countDown];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Button Action Methods
- (IBAction)startTimer:(id)sender {
[self updateCounter];
}
- (IBAction)stopTimer:(id)sender {
[appdelegate.countdownTimer invalidate];
labelCountdownTimer.text = #"00:00:00";
}
int countLimit=30; //seconds
NSDate *startDate;
- (void)countDown {
if([[NSDate date] timeIntervalSinceDate:startDate] >= countLimit) {
[appdelegate.countdownTimer invalidate];
return;
}
else {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = -([currentDate timeIntervalSinceDate:startDate]);
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
NSLog(#"timeString: %#",timeString);
NSLog(#"labelCountdownTimer: %#",labelCountdownTimer);
labelCountdownTimer.text = timeString;
}
}
- (void)updateCounter {
labelCountdownTimer.text = #"00:00:00";
startDate = [NSDate date];
appdelegate.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(countDown)
userInfo:nil
repeats:YES];
}
Thanks to everyone for your comments. I actually solved it by performing a method that will go and retrieve the value that the NSTimer is updating in my AppDelegate, since the method firing the NSTimer is no longer in the main thread when I leave the view and come back to it. This method will loop as long as my NSTimer is valid. I also placed a delay, allowing for the UI to update the value, and then perform the method again. Here is the code in case it helps someone running into a similar issue. I got this idea from the suggestion provided by chandan, thanks!!
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
}
#property (nonatomic, retain) NSTimer *countdownTimer;
#property (nonatomic, retain) NSString *timeString;
AppDelegate.m
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
}
#property (nonatomic, retain) NSTimer *countdownTimer;
#property (nonatomic, retain) NSString *timeString;
CountdownTimerViewController.h
#interface CountdownTimerViewController : UIViewController {
AppDelegate *appdelegate;
}
#property (strong, nonatomic) IBOutlet UILabel *labelCountdownTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStartTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStopTimer;
- (IBAction)startTimer:(id)sender;
- (IBAction)stopTimer:(id)sender;
CountdownTimerViewController.m
#implementation CountdownTimerViewController
#synthesize labelCountdownTimer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Instatiating Appdelegate
if(!appdelegate)
appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (void) viewDidAppear:(BOOL)animated {
if ([appdelegate.countdownTimer isValid]) {
[self updateLabel];
} else {
labelCountdownTimer.text = #"00:00:00";
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Button Action Methods
- (IBAction)startTimer:(id)sender {
[self updateCounter];
}
- (IBAction)stopTimer:(id)sender {
[appdelegate.countdownTimer invalidate];
labelCountdownTimer.text = #"00:00:00";
}
int countLimit=30; //seconds
NSDate *startDate;
- (void)updateCounter {
labelCountdownTimer.text = #"00:00:00";
startDate = [NSDate date];
appdelegate.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(countDown)
userInfo:nil
repeats:YES];
}
- (void)countDown {
if([[NSDate date] timeIntervalSinceDate:startDate] >= countLimit) {
[appdelegate.countdownTimer invalidate];
return;
}
else {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = -([currentDate timeIntervalSinceDate:startDate]);
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
appdelegate.timeString = [dateFormatter stringFromDate:timerDate];
labelCountdownTimer.text = appdelegate.timeString;
}
}
- (void) updateLabel {
if ([appdelegate.countdownTimer isValid]) {
labelCountdownTimer.text = appdelegate.timeString;
[self performSelector:#selector(updateLabel) withObject:nil afterDelay:0.05];
}
}
Type casting like this:
appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
won't actually make the UIApplicationDelegate into your AppDelegate class and add your extra parameters. Hence there will be no pointer to the timer in this variable.
You need a different approach for storing the timer pointer.
Try to update text on UILabel on main thread. Sometimes updation in UILabel not working on backgound thread.
- (void) viewDidAppear:(BOOL)animated
{
if ([appdelegate.countdownTimer isValid])
{
[self performSelectorOnMainThread:#selector(countDown) withObject:nil waitUntilDone:NO];
}
}
If your appdelegate object is working fine and UILabel is being updated with the current countdown time, but no subsequent updates to the UILabel happen then apply UI changes on main thread like it
- (void)countDown {
[self performSelectorOnMainThread:#selector(changeCountDownValue) withObject:nil waitUntilDone:NO];
}
- (void)changeCountDownValue
{
if([[NSDate date] timeIntervalSinceDate:startDate] >= countLimit) {
[appdelegate.countdownTimer invalidate];
return;
}
else {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = -([currentDate timeIntervalSinceDate:startDate]);
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
NSLog(#"timeString: %#",timeString);
NSLog(#"labelCountdownTimer: %#",labelCountdownTimer);
labelCountdownTimer.text = timeString;
}
}
please double check with NSTimer object. It should be working fine for UILabel updation. Please let me know if any problem still occurring.
I am new to iPhone Development, and am making a countdown project using navigation controller and storyboard. My application has two views. The first view only has one button. When this button is clicked, it goes to the second view. The second view has the countdown objects. My problem is that when the countdown is running in second view, if I go back to first view and then hit the button to go to the second view, the countdown is no longer running.
Here is the code:
view1.h
#import <UIKit/UIKit.h>
#import "view2.h"
#interface view1: UIViewController
-(IBAction)nextpage:(id)sender;
#end
view1.m
#implementation view1
-(IBAction)nextpage:(id)sender
{
view2 *next=[self.storyboard instantiateViewControllerWithIdentifier:#"secondview"];
[self.navigationController pushViewController:next animated:YES];
}
#end
view2.h
#interface view2 : UIViewController
{
IBOutlet UILabel *lbl;
IBOutlet UITextField *field;
NSTimer *theTimer;
NSDate *targetDate;
NSCalendar *cal;
NSDateComponents *components;
}
#property (nonatomic,retain) IBOutlet UILabel *lbl;
#property (nonatomic,retain) IBOutlet UITextField *field;
-(IBAction)back_first_view;
#end
view2.m
#implementation view2
#synthesize lbl,field;
- (void)viewDidLoad
{
cal = [[NSCalendar currentCalendar] retain];
components = [[NSDateComponents alloc] init];
}
- (IBAction)buttonPressed:(id)sender {
if (theTimer != nil) {
return;
}
NSString *input = field.text;
NSArray *timeSplit = [input componentsSeparatedByString:#":"];
NSUInteger hours = [[timeSplit objectAtIndex:0] intValue];
NSUInteger minutes = [[timeSplit objectAtIndex:1] intValue];
NSDate *now = [NSDate date];
NSDateComponents *dateComponents = [cal components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:now];
[dateComponents setHour:hours];
[dateComponents setMinute:minutes];
if (!targetDate) {
targetDate = [[cal dateFromComponents:dateComponents] retain];
}
else {
targetDate = nil;
targetDate = [[cal dateFromComponents:dateComponents] retain];
}
if ([targetDate timeIntervalSinceNow] > 0) {
theTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(tick) userInfo:nil repeats:YES];
[self hideKeyboard];
}
else {
targetDate = nil;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Cannot countdown because time is before now" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void)tick {
if ([targetDate timeIntervalSinceNow] <= 0) {
//Checks if the countdown completed
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Countdown Completed" message:#"YAY! The countdown has complete" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
components = [cal components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:[NSDate date] toDate:targetDate options:0];
NSInteger hours = [components hour];
NSInteger minutes = [components minute];
NSInteger seconds = [components second];
NSString *output = [NSString stringWithFormat:#"%i Hours\n%i Minutes\n%i Seconds\n", hours, minutes, seconds];
lbl.text = output;
}
- (void)hideKeyboard {
if ([field isFirstResponder]) [field resignFirstResponder];
}
- (IBAction)back_first_view
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
#end
Change this method to,
- (IBAction)nextpage:(id)sender
{
[self.navigationController pushViewController:self.next animated:YES];
}
And add the first line to your viewDidLoad or any such methods,
- (void)viewDidLoad {
[super viewDidLoad]; //Always keep super call as first call in a method
self.next = [self.storyboard instantiateViewControllerWithIdentifier:#"secondview"];
// Do any additional setup after loading the view.
}
And declare next in .h file #interface as,
#interface view1 : UIViewController
{
}
#property (nonatomic, strong) view2 *next;
Each and and every time when you are going to next page, you were creating a new view2, which you need to change.
Because you're using a UINavigationController, when you navigate back from View2 to View1, the View2 instance (and the timer running on it) is destroyed. When you navigate to View2 a second time, it's a brand-new instance.
For this to behave as you expect, you have to keep the timer alive somehow. You could modify your app delegate to manage the timer, and have View2 get its timer info from the delegate (for example).
I keep running into a pretty frustrating error in Xcode after implementing a date picker. The error in the debugger is: "Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: date"
I've been going through my code for hours now, and can't find the issue. It may be because I'm not checking for nil, there is no date the first time the app installs and launches, so that may be causing the crash. If it is, how do I check for nil in this code? I'm still very new at programming, any help would be much appreciated. Here is the code:
#import "DatePickerViewController.h"
#implementation DatePickerViewController
#synthesize datePicker;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Initialization code
}
return self;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm'/'dd'/'yyyy"];
NSDate *eventDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"DatePickerViewController.selectedDate"];
localNotif.fireDate = [eventDate dateByAddingTimeInterval:-13*60*60];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = #"Tomorrow!";
localNotif.alertAction = nil;
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 0;
[[UIApplication sharedApplication]presentLocalNotificationNow:localNotif];
return YES;
}
- (void)viewDidLoad {
NSDate *storedDate = [[NSUserDefaults standardUserDefaults]
objectForKey:#"DatePickerViewController.selectedDate"];
[self.datePicker setDate:storedDate animated:NO];
}
- (IBAction)dateChanged:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *selectedDate = [self.datePicker date];
[defaults setObject:selectedDate forKey:#"DatePickerViewController.selectedDate"];
}
You don't check if date is null, before using it, in ex.
(void)viewDidLoad {
NSDate *storedDate = [[NSUserDefaults standardUserDefaults]
objectForKey:#"DatePickerViewController.selectedDate"];
// add this check and set
if (storedDate == nil) {
storedDate = [NSDate date];
}
// ---
[self.datePicker setDate:storedDate animated:NO];
}
I've find a Debug way may help you debug where is the exception occurred and may help someone to debug with exception.
navigate to breakpoint
Click the add button, and choose exception Breakpoint
Add breakpoint and make exception type to Objective-C
Run the code
It will stop at the line which make crash happened!
Hope this help~