add a delay to my NSTimer after i press start game - ios

On my button to start my game i have a few NSTimers to make things scroll, i want to add a delay to these timers, not too sure how to though.
any advice?
Here's the buttons with 1 of the NSTimers
-(IBAction)StartGame:(id)sender{
StartGame.hidden = YES;
backgroundMovement = [NSTimer scheduledTimerWithTimeInterval:0.06 target:self selector:#selector(backgroundMoving)
userInfo:nil repeats:YES];
}
Thank you

When you call [NSTimer scheduledTimerWithTimeInterval:...] the time interval is the delay. You will be called back after the time interval you specify.
Alternatively, call performSelector:withObject:afterDelay:.
However, note please that there are deep flaws in your proposed architecture. A repeating timer with a .06 interval is a terrible idea, and more than one is an atrocious idea. You need to rethink this completely. Consider using real animation, or a display link, or sprite kit. Or something. Anything, really.

If you'd like to add a delay only once, when starting, you could implement a - (void)startTimers method, where you create and start your timers, then do
[self performSelector:#selector(startTimers) withObject:nil afterDelay:1.0f];
in your IBAction.
^ Don't copy-paste the performSelector method, as I might have made a typo, since I don't have Xcode open to verify.

Options to do this:
1) call a method with performSelector using a delay. In that method you create the NSTimer
[self performSelector:#selector(createTimer_backgroundMovement) withObject:nil
afterDelay:0.1];
2) if the delay is dependent of an action you can use this information in a flag and that flag can be used in the backgroundMoving method:
-(void) backgroundMoving {
if (!blAction_whichEnablesTimer) {
return;
}
// your backgroundMoving timer code
}
3) consider moving views with eg. block animations. Using block animations you can use delay also. Please see doc: https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html

Related

Objective C - Continue NSTimer after popping previous page

I have an NSTimer in a view controller which starts counting when the user presses a button. It counts down seconds for 3 minutes. What I want is that if the user wants to go back previous page (maybe go another page) and come back to this timer page, he/she should see counting timer label. I mean, I know timer continues to counting but when I load this page again, I cannot see its label as i left. Also I check my timer and get it's not considered as "valid".
I don't want to use AppDelegate for this purpose because I have many view controllers and this one is not that important. So, how can I achieve this continuous timer label? Should I use static timer or flag?
Thank you.
you cna implement a
static int counter = 0 ;
by having a selector method in the NSTimer and use that counter to continue the counting
[NSTimer scheduledTimerWithTimeInterval:180.0f
target:self
selector:#selector(updateTime:)
userInfo:nil
repeats:YES];
// Implement Method
-(void)updateTime: (NSTimer *) timer {
counter++;
self.label.text = counter;
}
Making the timer static might introduce nasty memory problems as it holds a reference to it's target.
But as that already is no problem for you seemingly, that'd be a good way to go. Better yet: create a singleton object for your timer that encapsulaten the NSTimer and the value it's counting. This way, your view controllers can use KVO on the value and are otherwise completely independent of the timer.

NSTimer to scroll UITableView is slow

I'm using NSTimer to fire a method that scrolls UITableView
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(scroller)
userInfo:nil
repeats:YES];
-(void)scroller
{
[self.row1TableView setContentOffset:CGPointMake(self.row1TableView.contentOffset.x, self.row1TableView.contentOffset.y - 50) animated:YES];
}
Problem is that the scrolling seems slow. It's closer to 1 second than .1 seconds in the interval.
What's the problem?
As far as I know, you can not change the default animation duration of setContentOffset:animated:. But what you can do is, setup a Core Animation display link (CADisplayLink - you can search for code samples on how to set up, but it is quite straight-forward. The class documentation should be a good place to start) and it will fire every frame, calling back a method you provide.
Inside that callback method, you can calculate how much you want to scroll your table view (how many points per frame), and call setContentOffset:animated: with the second parameter set to NO (immediate scrolling). You should implement some sort of easing to achieve better results.
Note: The reason for using CADisplayLink instead of NSTimer is, it is more reliable. It is what you would use in games before SpriteKit was available.
Addendum: This blog post has some sample code on how to setup the display link and the respective callback method.
Addendum 2: You can setup an instance variable to act as a "counter", and increment it by the ammount of time ellapsed since last frame, within each call of your callback (use properties duration and/or frameInterval). Once the counter reaches a critical value (that is, the animation has run for enough time) you can stop the display link update by calling the method:
-[CADisplayLink invalidate].
NSTimer that calls a selector on the current threads run loop. It may not be 100% precise time-wise as it attempts to dequeue the message from
the run loop and perform the selector.

NSTimer choppy when pressing buttons the second time a view loads

I'm creating a game view controller using an NSTimer to update a progress bar representing the remaining time of the current game round. This game view also displays a button performing some light core data updates.
When the remaining time is up, the timer is invalidated and a new view is pushed.
The first time the game view loads in the application life cycle, it works perfectly: no slowdowns when pressing the button and updating core data.
But when I'm pushing back the same game view in the application life cycle, button presses make the progress bar choppy and irresponsible.
Is the NSTimer not properly invalidated in the run loop? Should I use CADisplayLink instead, though my view isn't using a lot of resources?
Thanks in advance.
Here is my code:
Timer declaration in .h file :
#property (weak, nonatomic) NSTimer *updatetimer;
Timer creation in viewDidLoad:
self.updatetimer = [NSTimer timerWithTimeInterval:counterStep target:self selector:#selector(updateProgress) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.updatetimer forMode:NSRunLoopCommonModes];
updateProgress function :
- (void)updateProgress
{
//compute current time
currentTime = currentTime - counterStep;
//set timer label to int value of current time
self.timerLabel.text = [[NSString alloc] initWithFormat:#"%d",[[NSNumber numberWithDouble:currentTime] intValue]];
//update progress bar accordingly
[self.progressbar setProgress: currentTime / totalTime animated:YES];
if(currentTime <= 0)
{
//call the method that invalidates the timer + pushes to the next view
[self overallTimeEnd];
}
}
Timer invalidation:
[self.updatetimer invalidate];
self.updatetimer = nil;
There's not enough here to diagnose the problem. Given that you've confirmed that your initial timer is successfully invalidated, the next thing to check is to make sure that the problem is really that updateProgress is not getting called with the desired frequency (rather than whatever is updating the state variables that updateProgress relies upon).
But, let's assume that the problem is truly that updateProgress is not getting called with the desired frequency. If so, then it's probably something that you're running on that main thread that is preventing the timer from being able to run with the desired frequency. It's hard to say without seeing what updateProgress is doing, much less anything else you might have running on the main thread. WWDC 2012 video Building Concurrent User Interfaces on iOS illustrates how to use Instruments to find what might be adversely affecting the concurrent UX.
Finally, it's not clear underlying process that updateProgress is keeping us informed of, but if you can go to an event-driven approach (e.g. if network connection, update UI as didReceiveData is called rather than using a timer). Sometimes you have to use timers, but if you can avoid it, you might be able to improve the efficiency of the app.
So, finally found what was causing my timer not being deallocated over the application life cycle: I wasn't using unwind segues in my storyboard to go back between views but standard push segues.
Never used those before and didn't knew about them ...
Thanks to all of you for helping.

NSTimer incrementing whenever I get back to that view

I declared an nstimer on this event here:
-(void)layoutSubviews
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self selector:#selector(updateCounter:)
userInfo:_TimeLabel.text repeats:YES];
}
although its correct, the timer adds 1 more timer whenever I get back to this UITableViewCell causing a blinking effect (which is soooo noticeable specially when done back and forth). how do i fix this? is there a way to load the timer once and ignore the declaration once i get back to this UITableViewCell? pls help me. Im a newbie in Xcode.
layoutSubViews is called many a times. You can't be sure about when its called. When ever the view notices some changes and needs to re-render, then its layoutSubViews method is called.
I think for some reason layoutSubView is called twice.
Instead , initialise your timer in ViewDidLoad of ViewController.

Stop IOS animations appearing all at once

I have heard that IOS will batch animations.
for example, I have about 4 methods thats do some updates (on main thread) and when they are done, I call a method to fade in a image of a check mark showing its complete. (see below) However it seems they all appear at the same time. How could I make them appear after each method call?
[mySubClass1 UpdateAllGeneralData_Single];
[self FadeImageGeneralInfo];
[mySubClass1 UpdateAllMeetingData_Single];
[self FadeImageMeetingList];
[mySubClass1 UpdateAllSpeakerData_Single];
[self FadeImageSpeakerList];
You could use a timer to delay each subsequent call to FadeImage____List by a certain amount, or you could use the UIView animateWithDuration:delay:options:animations:completion: class method to delay each subsequent animation.
If you choose option 2, the easiest way to implement it is probably to change FadeImage______List to accept a delay argument. Then, for example (if each animation took 0.5 seconds):
[mySubClass1 UpdateAllGeneralData_Single];
[self FadeImageGeneralInfoWithDelay:0];
[mySubClass1 UpdateAllMeetingData_Single];
[self FadeImageMeetingListWithDelay:0.5];
[mySubClass1 UpdateAllSpeakerData_Single];
[self FadeImageSpeakerListWithDelay:1.0];

Resources