I am creating a game application in which I need to set timer of 2 minutes throughout the app screens in objective c.
I am creating it in viewDidLoad but it is creating a new instance every-time the view loads.
Here is the code which I am using :
#interface SomeViewController ()
{
int timerCounter;
NSTimer *timer;
}
#property (strong, nonatomic) IBOutlet UILabel *timerLbl;
#end
#implementation SomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self startCountdown];
}
- (void)startCountdown
{
timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(countdownTimer:)
userInfo:nil
repeats:YES];
}
- (void)countdownTimer:(NSTimer *)timer
{
timerCounter--;
int minutes = timerCounter / 60;
int seconds = timerCounter % 60;
NSString *string = [NSString stringWithFormat:#"%02d", minutes];
NSString *string2 = [NSString stringWithFormat:#"%02d", seconds];
NSString *timeTotal = [string stringByAppendingString:#":"];
NSString *timeTotal2 = [timeTotal stringByAppendingString:string2];
_timerLbl.text = timeTotal2;
if (timerCounter <= 0) {
[timer invalidate];
}
}
You need to invalidate it whenever the VC deallocates
- (void)dealloc {
[timer invalidate];
}
//
The second VC may look like this
#import "ggViewController.h"
NSInteger timerCounter = 120; // declared global to hold the value
#interface ggViewController ()
{
NSTimer*timer;
}
#end
#implementation ggViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// instead of using selector use this inline callback
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:true block:^(NSTimer * timer) {
timerCounter--;
int minutes = timerCounter / 60;
int seconds = timerCounter % 60;
NSString *string = [NSString stringWithFormat:#"%02d", minutes];
NSString *string2 = [NSString stringWithFormat:#"%02d", seconds];
NSString *timeTotal = [string stringByAppendingString:#":"];
NSString *timeTotal2 = [timeTotal stringByAppendingString:string2];
_timerLbl.text = timeTotal2;
if (timerCounter <= 0) {
[timer invalidate];
}
}];
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[timer invalidate];
}
- (IBAction)gg:(id)sender {
[self dismissViewControllerAnimated:true completion:nil];
}
#end
I have a pause IBAction & a resume IBAction, both for buttons, but I have game points I collect over the duration of the game play. How can I store the different game points integer values in the pause IBAction & pass them to the resume IBAction method.
NOTE: The pause IBAction invalidates all the NSTIMERS, and the resume IBAction recreates them.
Just to assist, I found a quick solution....but I'm sure there's a cleaner method:
In the vc.h:
NSMutableArray storeVariables;
In the vc.m
int a, b, c, d;
- (void)viewDidLoad
{
[super viewDidLoad];
a=0;
b=0;
c=0;
d=0;
storeVariables = [[NSMutableArray alloc] init];
}
-(IBAction)pauseButton:(id)sender{
a=3;
b=4;
c=5;
d=6;
[storeVariables addObject:[NSNumber numberWithInt:a]];
[storeVariables addObject:[NSNumber numberWithInt:b]];
[storeVariables addObject:[NSNumber numberWithInt:c]];
[storeVariables addObject:[NSNumber numberWithInt:d]];
NSLog(#"%d, %d, %d, %d", storeVariables[0], storeVariables[1], storeVariables[2], storeVariables[3]);
}
-(IBAction)resumeButton:(id)sender{
a = [storeVariables[0]];
b = [storeVariables[1]]
c = [storeVariables[2]]
d = [storeVariables[3]]
NSLog(#"%d, %d, %d, %d", a, b, c, d);
storeVariables = [[NSMutableArray alloc] init];
}
An IBAction is code. It can't store anything. You need to save your state somewhere like an instance variable of the object that implements the IBAction
This is what worked:
.h file-
#interface ViewController2 : UIViewController{
NSMutableArray *savedScoreData;
int PlayTimer;
int timeMinute;
int bonusPts;
int enemykill;
}
.m file-
- (void)viewDidLoad {
PlayTimer = 0;
timeMinute = 0;
bonusPts = 0;
timeMinute = 0;
savedScoreData = [[NSMutableArray alloc] init];
}
- (IBAction)pauseButton:(id)sender {
NSLog(#"pause-before: %d, %d, %d,",PlayTimer,enemykill,bonusPts);
[GameTimer invalidate]; //this constantly changes the PlayTimer & timeMinute variables
[characterTimer invalidate];
[enemyTimer invalidate]; //this constantly changes the enemyKill & bonusPts variables
[_bonusImgHolder removeFromSuperview];
if([_soundEnable isEqualToString:#"YES"]){
[_player2 pause];
}
//NSLog(#"%tu",_player2.playing);
_resumeButton.hidden = NO;
_pauseButton.hidden = YES;
NSLog(#"pause-after: %d, %d, %d,",PlayTimer,enemykill,bonusPts);
//[sender num :PlayTimer];
[savedScoreData addObject:[NSNumber numberWithInteger: PlayTimer]];
[savedScoreData addObject:[NSNumber numberWithInteger: timeMinute]];
[savedScoreData addObject:[NSNumber numberWithInteger: enemykill]];
[savedScoreData addObject:[NSNumber numberWithInteger: bonusPts]];
NSLog(#"%i", [savedScoreData[0] intValue]);
NSLog(#"%d", [savedScoreData[1] intValue]);
NSLog(#"%d", [savedScoreData[2] intValue]);
NSLog(#"%d", [savedScoreData[3] intValue]);
}
- (IBAction)resumeButton:(int)pauseButton{
NSLog(#"resume-before: %d, %d, %d,",PlayTimer,enemykill,bonusPts);
PlayTimer = [savedScoreData[0] intValue];
timeMinute = [savedScoreData[1] intValue];
enemykill = [savedScoreData[2] intValue];
bonusPts = [savedScoreData[3] intValue];
NSLog(#"%d", (int)enemykill);
_resumeButton.hidden = YES;
_pauseButton.hidden = NO;
if([_soundEnable isEqualToString:#"YES"]){
[_player2 play];
}
GameTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(CollectPoints) userInfo:nil repeats:YES];
characterTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(Jumping) userInfo:nil repeats:YES];
enemyTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(enemyTravel) userInfo:nil repeats:YES];
NSLog(#"resume-after: %d, %d, %d,",PlayTimer,enemykill,bonusPts);
[savedScoreData removeAllObjects];
}
I have a UIPickerView array of seconds which i would like to link to an NSTimer.
in quiz.h file
#property (strong, nonatomic) IBOutlet UIPickerView *timePicker;
i have the array in quiz.m file:
- (void)viewDidLoad {
[super viewDidLoad];
self.pickerData = #[#"1 second", #"2 seconds", #"3 seconds", #"4 seconds", #"5 seconds"];
self.timePicker.dataSource = self;
self.timePicker.delegate = self;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
[self.pickerData objectAtIndex:[self.timePicker selectedRowInComponent:0]];
}
and i would like to link this array of seconds to a property in the imageview.h file
#property (nonatomic, assign) int seconds;
how can i do that within the quiz.m file?
i am trying:
ImageViewController *ivc = [[ImageViewController alloc] init];
ivc.seconds = [self.timePicker selectedRowInComponent:0]; // warning displays conversion loses integer precision
what do i add in ivc.seconds to link it to the picker array and get the number seconds in each row when selected?
i want to link the seconds to a NSTimer.
[NSTimer scheduledTimerWithTimeInterval:self.seconds target:self selector:#selector(timeout)
userInfo:nil repeats:NO];
timeout method pops to rootview
make self.pickerData = #[#"1", #"2", #"3", #"4", #"5"]; and in picker methods,
- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
int value = [[self.pickerData objectAtIndex:row] intValue];
NSString *secondString = (value > 1) ? #"seconds" : #"second"
NSString *title = [NSString stringWithFormat:#"%# %#", [self.pickerData objectAtIndex:row], secondString];
return title;
}
and on creating
NSInteger row = [self.timePicker selectedRowInComponent:0];
ImageViewController *ivc = [[ImageViewController alloc] init];
ivc.seconds = [[self.pickerData objectAtIndex:row] intValue];
to show the count down timer, set up tim er first
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(setTimeToLabel) userInfo:nil repeats: YES];
then in setTimeToLabel method
-(void) setTimeToLabel
{
if (self.seconds != 0) {
self.timeLabel.text = [NSString stringWithFormat:#"%d", self.seconds];
self.seconds = self.seconds - 1;
} else {
[timer invalidate];
}
}
I am writing a simple program that, I display a number from array 1 on a label and then move the number to array 2. However, the array keeps returning empty.
Here's my code.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self firstArrayInit];
[self secondArrayInit];
[self tranferA1toA2];
}
-(NSMutableArray *) firstArrayInit{
self.originalArray = [NSMutableArray array];
for (int i=0; i<16; i++) {
[self.originalArray addObject:[NSNumber numberWithInteger:i]];
}
return self.originalArray;
}
-(NSMutableArray *)secondArrayInit{
self.secondArray = [NSMutableArray array];
return self.secondArray;
}
-(void) tranferA1toA2{
self.mytimer = [NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:#selector(displayNumber)
userInfo:nil
repeats:YES];
}
-(NSMutableArray *)addToSecondArray:(int)myNumber{
[self.secondArray addObject:[self.originalArray objectAtIndex:myNumber]];
return self.secondArray;
}
-(void) displayNumber{
static int num=0;
if (num < level){
myLabel.text = [NSString stringWithFormat:#"%#", [self.originalArray objectAtIndex:num]];
[self addToSecondArray:num];
}
else{
[self.mytimer invalidate];
[myLabel setText:#""];
}
num++;
}
I've tried printing out the values in array 2 from displayNumber and it works. But, outside the function the array is empty.
Your code works as it is supposed to. The problem is that you check the array too early, even before the timer is fired for the first time. Check the array after the timer is invalidated
I have an NSTimer in another function but I want to be able to wait for the NSTimer to become invalidated before continuing on with the code is there a way to do this?
- (IBAction)addLifePoints:(UIButton *)sender
{
[[ARCHDuelCalculator sharedARCHDuelCalculator] setLifePointDelta:[NSNumber numberWithInt: [self.hiddenTextField.text intValue]]];
[[ARCHDuelCalculator sharedARCHDuelCalculator] setAddOrSubstract: YES];
[[ARCHDuelCalculator sharedARCHDuelCalculator] applyingDeltaToLifePointsByDelta];
// This will animate the life points
animationTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(animateLifePoints) userInfo:nil repeats:YES];
// This is where we bring it back to the view controller
self.duelistOneLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistOneLifePoints stringValue];
self.duelistTwoLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistTwoLifePoints stringValue];
self.hiddenTextField.text = #"";
[self syncTextField: self.hiddenTextField];
[self.hiddenTextField resignFirstResponder];
}
- (void) animateLifePoints
{
NSNumber *sections = [[ARCHDuelCalculator sharedARCHDuelCalculator] getLifePointSections];
for(int timer = 0; timer < 100; ++timer)
{
self.duelistOneLifePoints.text = [[[ARCHUtilities sharedARCHUtilities] subtractTwoNSNumbersByDataType:#"int" firstNumber:[NSNumber numberWithInt: [self.duelistOneLifePoints.text intValue]] secondNumber:sections] stringValue];
if ((timer % 14) == 0)
{
[self playLifePointSound:#"mainLifePointSound" typeOfFile:#"mp3"];
}
}
[animationTimer invalidate];
}
hope this works:
-split addLifePoints into 2 methods.
-put code after the nstimer in another method (newMethod)
-call newMethod right after the nstimer is invalidated.
- (IBAction)addLifePoints:(UIButton *)sender
{
[[ARCHDuelCalculator sharedARCHDuelCalculator] setLifePointDelta:[NSNumber numberWithInt: [self.hiddenTextField.text intValue]]];
[[ARCHDuelCalculator sharedARCHDuelCalculator] setAddOrSubstract: YES];
[[ARCHDuelCalculator sharedARCHDuelCalculator] applyingDeltaToLifePointsByDelta];
// This will animate the life points
animationTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(animateLifePoints) userInfo:nil repeats:YES];
}
- (void) animateLifePoints
{
NSNumber *sections = [[ARCHDuelCalculator sharedARCHDuelCalculator] getLifePointSections];
for(int timer = 0; timer < 100; ++timer)
{
self.duelistOneLifePoints.text = [[[ARCHUtilities sharedARCHUtilities] subtractTwoNSNumbersByDataType:#"int" firstNumber:[NSNumber numberWithInt: [self.duelistOneLifePoints.text intValue]] secondNumber:sections] stringValue];
if ((timer % 14) == 0)
{
[self playLifePointSound:#"mainLifePointSound" typeOfFile:#"mp3"];
}
}
[animationTimer invalidate];
[self newMethod]; //////////////////// ADD THIS LINE ALSO, continue code
}
-(void)newMethod{
//...so continue code...
// This is where we bring it back to the view controller
self.duelistOneLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistOneLifePoints stringValue];
self.duelistTwoLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistTwoLifePoints stringValue];
self.hiddenTextField.text = #"";
[self syncTextField: self.hiddenTextField];
[self.hiddenTextField resignFirstResponder];
}