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.
Related
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.
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];
}
been having this problem for a few days now and can't seem to find a solution for it. It's probably some very basic stuff but still can't come up with a solution. So I'm trying to have my uilabel update a user speed in a car or on bike. But When the UIlabel update, it doesn't update the correct value. Any help will be appreciated.
Heres my .h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MainViewController : UIViewController <LoginDelegate,WEPopoverParentView,PopoverControllerDelegate,MainMenuDelegate,MKMapViewDelegate,UIActionSheetDelegate,UIAccelerometerDelegate, CLLocationManagerDelegate, NSObject>
{
AppDelegate *appDelegate;
IBOutlet MKMapView *userMap;
CLLocationManager *locationManager;
}
#property (strong, nonatomic) IBOutlet UILabel *speedView;
#property(nonatomic) int speedCount;
#property (nonatomic,retain) CLLocationManager *locationManager;
#property (nonatomic, strong) WEPopoverController *popoverController;
+ (NSString *) speedToMPH: (float) value;
- (IBAction)btnMenuTapped:(id)sender;
#end
and my .h file
#implementation MainViewController
#synthesize speedCount;
#synthesize speedView;
#synthesize popoverController;
#synthesize locationManager;
- (void)locationError:(NSError *)error {
speedView.text = [error description];
}
-(void)viewWillAppear:(BOOL)animated
{
[userMap setRegion:MKCoordinateRegionMakeWithDistance(userMap.userLocation.coordinate, 5, 5) animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = [[UIApplication sharedApplication] delegate];
locationManager =[[CLLocationManager alloc] init];
// Do any additional setup after loading the view, typically from a nib.
[userMap setCenterCoordinate: userMap.userLocation.coordinate animated: YES];
[self performSelector:#selector(checkForLogin) withObject:nil afterDelay:1];
[self startLocationServices];
// create LM
self.locationManager = [CLLocationManager new];
// set its delegate
[self.locationManager setDelegate:self];
// set configuration
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
// start location services
[self.locationManager startUpdatingLocation];
// create an oldLocation variable if one doesn't exist
}
- (void)startLocationServices
{
// create the Location Manager
if (self.locationManager == nil) {
self.locationManager = [CLLocationManager new];
}
// stop services
[self.locationManager stopUpdatingLocation];
[self.locationManager setDelegate:nil];
self.speedView.text = #"Location Services stopped.";
}
// locationManager didUpdateToLocation FromLocation
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"%#", newLocation);
self.speedView.text = [NSString stringWithFormat:#"%d %.f ", speedCount, [newLocation speed]];
}
+ (NSString *) speedToMPH: (float) value
{
NSString *speedCount = #"0.0 ";
if (value>0) {
float mile = 1609.344f;
float mph = value / mile * 3600;
speedCount = [NSString stringWithFormat: #"%.f ", mph];
}
return speedCount;
}
CLLocation returns the speed in meters per second. So you will have to convert it to miles per hour by multiplying the value with 2.23694.
self.speedView.text = [NSString stringWithFormat:#"%d %.f ", speedCount, [newLocation speed] * 2.23694];
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 finally got my leaderboard to show up. Now I just need to implement that my score will pop up.
My score is saved as an NSString in NSUserDefaults under the name score.
Here is some code:
Game_CenterViewController.h
#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>
#import "GameCenterManager.h"
#class GameCenterManager;
#interface Game_CenterViewController : UIViewController <UIActionSheetDelegate, GKLeaderboardViewControllerDelegate, GKAchievementViewControllerDelegate, GameCenterManagerDelegate> {
GameCenterManager *gameCenterManager;
int64_t currentScore;
NSString *currentLeaderBoard;
}
#property (nonatomic, retain) GameCenterManager *gameCenterManager;
#property (nonatomic, assign) int64_t currentScore;
#property (nonatomic, retain) NSString* currentLeaderBoard;
#end
Game_CenterViewController.m
#import "Game_CenterViewController.h"
#import "AppSpecificValues.h"
#import "GameCenterManager.h"
#implementation Game_CenterViewController
#synthesize gameCenterManager;
#synthesize currentScore;
#synthesize currentLeaderBoard;
- (void)dealloc {
[gameCenterManager release];
[currentLeaderBoard release];
[currentScoreLabel release];
[super dealloc];
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.currentLeaderBoard = thescore101;
self.currentScore = score
if ([GameCenterManager isGameCenterAvailable]) {
self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
} else {
// The current device does not support Game Center.
}
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController {
[self dismissModalViewControllerAnimated: YES];
[viewController release];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.gameCenterManager = nil;
self.currentLeaderBoard = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
The current score is where I'm trying to put the NSString in.
EDITED: I think it would be better to use int for the currentScore.
Is this what you are looking for?
- (void)submitMyScore:(int64_t)score
{
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:#"yourCat"] autorelease];
myScoreValue.value = (int)score;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted: %d",(int)score);
}
}];
}
So you should add a IBAction
- (IBAction)buttonPressed
{
[self submitMyScore:currentScore];
}
With this and connecting the SEND MY SCORE button to this IBAction, you will have your score submitted.
I hope this to be useful for you.