I am sending users location to the server through web service, in the response I get interval to send next location. I am using the following call to send locations using timer but when I get the different value the timer still uses the old value. I also tried to invalidate the timer to set the new value but seems not working
I have global variable
long counter= 10;
self.timer = [NSTimer scheduledTimerWithTimeInterval:counter target:self selector:#selector(updateLocation) userInfo:nil repeats:YES];
- (void)updateLocation {
CLLocation *location = self.locationManager.location;
....
counter = 30;
}
I followed the couple of post from stack overflow but did not get it working.
In short, I need to send the updated location based on the response!
#interface MyClass()
#property (strong, nonatomic) NSTimer *timer;
#property (nonatomic) CGFloat counter;
#end
#implementation MyClass
- (void)viewDidLoad
{
[super viewDidLoad];
//set initial value for timer
self.counter = 10;
[self resetTimer];
}
//...
- (void)resetTimer
{
[self.timer invalidate]
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.counter target:self selector:#selector(updateLocation) userInfo:nil repeats:NO];
}
- (void)updateLocation
{
CLLocation *location = self.locationManager.location;
//...
self.counter = 30;
[self resetTimer];
}
//...
- (void)dealloc
{
//invalidate timer to avoid zombie objects (EXC_BAD_ACCESS crash)
[self.timer invalidate];
}
#end
Related
Got an issue with my countdown timer who don't want to countdown from 60 and reset when 0 is reached. At the moment it just sets its label 0 and start counting down to -1, 2-... How do I get it to start from 60 on iOS in xcode?
.m file
#import "ViewController.h"
#interface ViewController ()
{
int timeTick;
NSTimer *timer;
}
#end
#implementation ViewController
- (IBAction)stopStartBtn:(id)sender {
[timer invalidate];
timeTick = 3;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(myTicker) userInfo:nil repeats:YES];
}
-(void)myTicker{
timeTick--;
NSString *timeString =[[NSString alloc] initWithFormat:#"%d", timeTick];
self.display.text = timeString;
if(timer >= 0){
[timer invalidate];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
timeTick = 3;
}
#end
.h File
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *display;
- (IBAction)stopStartBtn:(id)sender;
#end
Your code currently starts the timer at 0, decrements it, and then checks it it has reached 60. Obviously that won't happen.
If you want to start at 60 and stop at 0 then you need to set timeTick to 60 in viewDidLoad and check for a value of 0 in myTicker.
And don't forget to call [super viewDidLoad]; in your viewDidLoad method.
You also need to fix your check to see if you've reached zero. Right now you are looking at the timer pointer instead of timeTick integer.
Change:
if(timer >= 0){
[timer invalidate];
}
to:
if (timeTick <= 0) {
[timer invalidate];
}
You are also never setting your timer instance variable. You actually set a local variable of the same name.
Change:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(myTicker) userInfo:nil repeats:YES];
to:
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(myTicker) userInfo:nil repeats:YES];
#interface Ovning1 ()
{
int timeTick;
NSTimer *timer;
}
#end
#implementation Ovning1
- (IBAction)stopStartBtn:(id)sender {
[timer invalidate];
timeTick = 60;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(myTicker) userInfo:nil repeats:YES];
}
-(void)myTicker{
timeTick--;
NSString *timeString =[[NSString alloc] initWithFormat:#"%d", timeTick];
self.display.text = timeString;
if(timeTick <= 0){
[timer invalidate];
}
}
Right now here is the code I'm using. It only updates when the button is pressed and is the average rather than instantaneous.
-(IBAction)button:(id)sender {
[self incrementTapCount];
NSMutableString *aString = [NSMutableString stringWithFormat:#"%.2f", averageTapsPerSecond];
[aString appendFormat:#"%s", " per second"];
current.text = aString;
}
- (void)incrementTapCount
{
tapCountInPastSecond++;
}
- (void)timerActions
{
secondsElapsed = secondsElapsed + .1;
averageTapsPerSecond = (averageTapsPerSecond*(secondsElapsed-.1) +tapCountInPastSecond) / secondsElapsed ;
tapCountInPastSecond = 0;
}
On the view did load...
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(timerActions) userInfo:Nil repeats:YES];
I'm trying to get it to update without pressing the button, and not be the average speed, rather the speed at that moment.
Your timer fires every .1 second and you want to keep a "sliding" total of the taps in the last second. I would suggest an array of 10 integers. Each time the timer ticks you can add the most recent tap count to the end of the array and subtract the oldest.
#property (assign) NSInteger runningTotal;
#property (assign) NSInteger tapsInLastSample;
#property (strong,nonatomic) NSMutableArray *tapHistory;
-(void) viewDidLoad {
[super viewDidLoad];
self.runningTotal=0;
self.tapHistory=[NSMutableArray arrayWithCapacity:11];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(timerActions) userInfo:Nil repeats:YES];
}
-(IBAction)button:(id)sender {
self.tapsInLastSample++;
}
- (void)timerActions {
self.runningTotal+=self.tapsInLastSample;
[self.tapHistory addObject:[NSNumber numberWithInteger:self.tapsInLastSample]];
if (self.tapHistory.count >10) {
self.runningTotal-=[self.tapHistory[0] integerValue];
[self.tapHistory removeObjectAtIndex:0];
}
current.text=[NSString stringWithFormat:#"Taps in last second=%ld",(long)self.runningTotal];
self.tapsInLastSample=0;
}
So I have a method called: - (void)spawnNode and it basically regulates the spawning of my Node. My problem is that I want to make it so that when the BOOL runGame equals YES the spawnNode method will begin and keep spawning my node after intervals of time. Which I don't know how to do.
The BOOL runGame is initially set to NO.
Below is the full spawnNode method:
- (void)spawnNode{
//Spawn Interval Duration
spawnIntervalDuration = 0.75;
//SKAction spawnInterval
spawnInterval = [SKAction waitForDuration:spawnIntervalDuration];
if(runGame){
[self runAction:spawnInterval completion:^{
[self generateNode];
}];
}
}
So, How do I make this method always run whilst runGame is equal to YES?
You can create a property:
#property (nonatomic, assign) BOOL runGame;
Also, a NSTimer property:
#property (nonatomic) NSTimer *timer;
Then, you need to override the setter for it:
- (void)setRunGame:(BOOL)newValue
{
if (newValue == YES) {
[self spawnNode];
CGFloat spawnInterval = 0.75;
self.timer = [NSTimer scheduledTimerWithTimeInterval:spawnInterval
target:self
selector:#selector(spawnNode)
userInfo:kNilOptions
repeats:YES];
} else {
[self.timer invalidate];
self.timer = nil;
}
}
#interface Taxi_MainViewController : Taxi_BaseNavViewController
{
__block NSTimer *timer_;
}
[Taxi_do_order psg_place_orderWithMemberId:strMemberId_ orderStatus:K_orderStatus_open andCLLocationCoord:location.coordinate callback:^(NSInteger iOrderId){
[Taxi_StatusView dismiss];
if (iOrderId >=0)
{
isOrderExist = YES;
[weakSelf_ showWaittingDriverAcceptView];
timer_ = [NSTimer scheduledTimerWithTimeInterval:2.0
target:weakSelf_
selector:#selector(actListen:)
userInfo:nil
repeats:YES];
}else
[weakSelf_ hideWaittingDriverAcceptView];
}faile:^(){
[Taxi_StatusView showLostNetWork];
}];
when i call [timer_ invalidate],timer_ = nil; at other method, the timer function still call every 2 second.
In your case, the variable timer_ is never keep, and you lose the pointer
at the end block scope. With a property you have retain / release mechanism.
Try this :
#interface Taxi_MainViewController : Taxi_BaseNavViewController
{
}
#property (nonatomic,retain) NSTimer* timer;
#end
[Taxi_do_order psg_place_orderWithMemberId:strMemberId_ orderStatus:K_orderStatus_open andCLLocationCoord:location.coordinate callback:^(NSInteger iOrderId){
[Taxi_StatusView dismiss];
if (iOrderId >=0)
{
isOrderExist = YES;
[weakSelf_ showWaittingDriverAcceptView];
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:weakSelf_
selector:#selector(actListen:)
userInfo:nil
repeats:YES];
}else
[weakSelf_ hideWaittingDriverAcceptView];
}faile:^(){
[Taxi_StatusView showLostNetWork];
}];
Sorry this is a repeat question, but I have tried all the solutions I could find without success.
Anyway, here is my problem, specifically. I have the following code where I start a timer on a long press gesture, then stop it when that gesture is cancelled or when the action is complete.
-(void)photoLongPress:(UILongPressGestureRecognizer *)press
{
NSTimer *timer = nil;
if (press.state == UIGestureRecognizerStateBegan)
{
//Start timer
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(photoLongPressTimer:) userInfo:nil repeats:YES];
}
if (press.state == UIGestureRecognizerStateEnded)
{
[timer invalidate];
timer = nil;
}
}
-(void)photoLongPressTimer:(NSTimer *)timer
{
DAProgressOverlayView *progress = (DAProgressOverlayView *)[self.view viewWithTag:kTagPhotoDeleteProgressIndicator];
progress.progress += 0.08;
if (progress.progress == 1)
{
[self deletePhotoSelection];
[timer invalidate];
timer = nil;
}
}
The timer stops when invalidated in the photoLongPressTimer method, but not if the gesture stops in the photoLongPress method. Why might this be? I'm stumped.
Thanks.
You need to store timer in an instance variable so that you can refer to it later. It works in photoLongPressTimer: because the timer is passed as a parameter but in photoLongPress: it is nil because you haven't just created it and it's a local reference.
Add a property:
#property (strong, nonatomic) NSTimer *timer;
Store the new timer into it:
self.timer = [NSTimer schedu...
Invalidate and nil the property:
[self.timer invalidate];
self.timer = nil;
NSTimer *timer = nil;
This line only creates a local variable.
You must make a property for the timer.
Put this in your .h file.
#property (strong) NSTimer *timer;
Then use the code here
-(void)photoLongPress:(UILongPressGestureRecognizer *)press
{
if (press.state == UIGestureRecognizerStateBegan)
{
//Start timer
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(photoLongPressTimer:) userInfo:nil repeats:YES];
}
if (press.state == UIGestureRecognizerStateEnded)
{
[self.timer invalidate];
self.timer = nil;
}
}
-(void)photoLongPressTimer:(NSTimer *)timer
{
DAProgressOverlayView *progress = (DAProgressOverlayView *)[self.view viewWithTag:kTagPhotoDeleteProgressIndicator];
progress.progress += 0.08;
if (progress.progress == 1)
{
[self deletePhotoSelection];
[timer invalidate];
timer = nil;
}
}
Problem is with NSTimer *timer = nil;
in -(void)photoLongPress:(UILongPressGestureRecognizer *)press
method.
remove NSTimer *timer = nil; from this method and store instance of NSTimer.