viewWillAppear blocks all Animations - ios

I have a GLKView because I use some OpenGLES for some animations with some graphics.
All these animations are working very good until I implement a viewWillAppear method.
I have two timers intialized in the viewDidLoad:
updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(updateScene) userInfo:nil repeats:YES];
paintTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:#selector(paintScene) userInfo:nil repeats:YES];
NSLog tells me that the two methods (updateScene and paintScene) are called correctly
and my graphics are changed correctly.
Now as long as I have no viewWillAppear method everything animates fine.
When I implement a viewWillAppear method, updateScene and paintScene are still
called but nothing changes. no animation. viewWillAppear is empty. no code inside.
Why are all animations blocked?

Make sure viewWillAppear calls [super viewWillAppear:animated];
This may fix your problem. Per Apple's docs:
If you override this method, you must call super at some point in your
implementation.

Related

calling method repeatedly after 3 seconds time interval in background

I have gone through many sites but still no answer.
I have a method suppose void xyz(), which will get called automatically from a View Controller after every 3 seconds.
I have no idea what to use, do I have to use NSThread or PerformSelector.
Call this method from ViewDidLoad method.ViewDidLoad will when your view will be appear in iPhone device or Simulator.
[NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:#selector(runMethod) userInfo:nil repeats:YES];
-(void)runMethod
{
}
Something like this
-(void)xyz{
[self performSelectorInBackground:#selector(xyz) withObject:nil];
}
- (void)viewDidLoad {
[self performSelector:#selector(xyz) withObject:nil afterDelay:0.3];
}
Use NSTimer
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:#selector(xyz) userInfo:nil repeats:YES];
You should use NSTimer as mentioned by #mokujin.
Please visit https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html

NSTimer does not stop

[self performSelectorInBackground:#selector(method) withObject:nil];
-(void)method
{
timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(getLastImageName1) userInfo:nil repeats:YES];
runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer1 forMode:NSRunLoopCommonModes];
[runLoop run];
}
-(void)viewdidunload
{
[timer1 invalidate];
timer1=nil;
}
I start Timer in HomeViewController even I invalidate, it keeps running in OtherViewController. What is wrong with my code?
First of all, when you're overriding life cycle methods, you should include a call to the super version of that method.
Second of all, Objective-C is case sensitive, so even if your app would try to call the life-cycle even, viewDidUnload, your method would simply never be called because that's what you titled your method.
Third of all, viewDidUnload was deprecated in iOS 6.0 and shouldn't be used at all by this point unless you're going way out of your way to support backward compatibility. It will never be called in iOS 6.0 and greater.
If you want the timer to stop when the user navigates away from the current view, you'll want something like this:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if (timer1.isValid) {
[timer1 invalidate];
}
timer1 = nil;
}
If you're looking for something else, you'll need to elaborate on what it is you want to accomplish exactly.
If you ARE working on a pre-iOS 6.0 project, for whatever reason, the reason your method isn't being called is at least in part because it is spelled wrong. Again, Objective-C is case sensitive. Your method name should be spelled viewDidUnload.
For future reference, the question shouldn't really be "why isn't my timer invalidating?" You should have start by using breakpoints or NSLog statements to determine whether or not your method, viewdidunload, which tries to invalidate the timer even fires. When you find out it's not being called, do a search to ask "How come viewdidunload isn't called?" Then you'll go fix the capitalization problem and the problem will (probably) remain, so do some more research. And if at the end, you still can't figure it out, as a worst case scenario, the post question should be "how come viewdidunload isn't called?"
timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(getLastImageName1:) userInfo:nil repeats:YES];
set colon for function in selector
-(void) getLastImageName1 :(NSTimer*)timer1
{
//Do your all process and invalidate after completion
[timer1 invalidate];
}
or if you want to remove timer after moving to next view controller use how #nhgrif mentioned
- (void)viewDidDisappear:(BOOL)animated
{
[timer1 invalidate];
}
[self performSelector:#selector(method) withObject:nil afterDelay:0.0];
-(void)method
{
timer1 = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(getLastImageName1) userInfo:nil repeats:YES];
runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer1 forMode:NSRunLoopCommonModes];
[runLoop run];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[timer1 invalidate];
timer1=nil;
}
There is no need to add the timer (again) on the main run loop. Or is it necessary for You to run it also in commonModes? For me it was never necessary.
From the NSTimer Documentation:
scheduledTimerWithTimeInterval:invocation:repeats:
Creates and returns a new NSTimer object and schedules it on the
current run loop in the default mode.
Since the NSRunLoop Documentation points out that you can add timer on several run loop modes, maybe this is the problem.
addTimer:forMode:
Discussion You can add a timer to multiple input modes. While running
in the designated mode, the receiver causes the timer to fire on or
after its scheduled fire date. Upon firing, the timer invokes its
associated handler routine, which is a selector on a designated
object.
Also I don't get why you are invoking the timer creation with performSelector?
I just wrote a minimalistic sample. thats totally working!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(doWork:) userInfo:Nil repeats:YES];
}
- (void)viewDidDisappear:(BOOL)animated{
[self.timer invalidate];
[super viewDidDisappear:animated];
}
- (void) doWork:(id) userInfo
{
NSLog(#"Working again");
}
Hope this helps.
-(void)viewDidUnload is a delegate which fires on memory warning only and is deprecated after iOS 6. It will also never fire on the simulator.
Stop timer in
- (void)viewWillDisappear:(BOOL)animated
or in
- (void)viewDidDisappear:(BOOL)animated

Weird behavior of NSTimer in class

I have a real weird behavior of NSTimer object.
I'm trying to call ChangePic method with repeat counts of 2 seconds, But the timer isn't repeating. and i have this problem only in 1 class in the project
I have 5 View Controllers in my App, and the same code works in all classes except this one.
Does anybody has idea how could it be? is it possible that something blocking the timer ?
-BTW, ChangePic Method is called only once, and not repeating.
My Code:
ViewController.h
#property (nonatomic, strong) NSTimer *timer;
ViewController.m
_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(ChangePic) userInfo:nil repeats:YES];
[_timer fire];
-(void) ChangePic {
NSLog(#"testing");
}
Assign it to the property not the backing variable.
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(ChangePic) userInfo:nil repeats:YES];
It's difficult to say exactly what your issue is given that there isn't a whole lot of background given. I can tell you that I answered another question where the problem turned out to be the fact that one of the views was blocking the timer. Timers can run on a number of different modes and different scenarios can cause the timer to sometimes be blocked. Try adding the timer to all common modes like this:
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
Also, like #Hejazi said, remove the 'fire' method call. It's not needed on a scheduled timer.

how to invalidate NSTimer?

self.timerProgress=[NSTimer scheduledTimerWithTimeInterval:50.0 target:self selector:#selector(stopProgressView) userInfo:nil repeats:NO];
-(void)stopProgressView
{
if ([self.timerProgress isValid]) {
[self.timerProgress invalidate];
self.timerProgress=nil;
}
}
and on a button click when i tried to invalidate NSTimer object
-(void)cancelTimer
{
if ([self.timerProgress isValid]) {
[self.timerProgress invalidate];
self.timerProgress=nil;
}
}
it don't get invalidate. It calls once stopProgressView after the interval of 50.
How to get resolve from this issue?
- (IBAction)stopTimer {
if ([timerProgress isValid]) {
[timerProgress invalidate];
}
}
Don't use self.timerProgress use just timerProgress
The most likely reason for this is that your timer scheduled on a different run loop to the one where you try and invalidate it.
Timers must be invalidated on the same thread/runloop as the run loop that they are scheduled on.
Cocoa touch isn't thread safe, so you should be running all UI related activities on the main thread. It may work if you do GUI work on different threads, but then you'll get random crashes, and you'll also generate timer problems like this.
It seems like from what you're posting it should work. This is how I have it in my apps and it works fine.
However, you could try making the selector one that takes a timer object like:
-(void)stopProgressView:(NSTimer *)timer{
//do stuff with timer here
}
Note that this would also mean that you should change #selector(stopProgressView) to #selector(stopProgressView:). Although for the record my current stop timer function just uses [self.timer invalidate] and it works fine.
My other piece of advice for debugging is to use NSLogs to make sure each of the methods are in fact getting called, and that when the method is called an NSLog within the if clause to make sure that works.
You create NSTimer with out NSRunLoop so your NSTimer not started, to add this code after
self.timerProgress = [NSTimer scheduledTimerWithTimeInterval:50.0
target:self
selector:#selector(stopProgressView)
userInfo:nil
repeats:NO];
//add
[[NSRunLoop currentRunLoop] addTimer:_tapTimer
forMode:NSDefaultRunLoopMode];

Why would my timer work on the iPad simulator but not on the iPad?

I'm working with all UIKit, and—for prototyping purposes have just shoved all the logic into the main viewController. I create some UIViews in viewDidLoad, hide some, and then set an NStimer to unhide the hidden ones in 4 seconds. This timer fires perfectly in the simulator, but will never fire on the iPad. Why could this happen and what should I even be looking for?
This is where I set my view and timer.
- (void)viewDidLoad {
[super viewDidLoad];
//snipped out long code that adds UIViews as subviews and runs fine
curtainView.hidden=YES;
questionLabel.hidden=YES;
[NSTimer scheduledTimerWithTimeInterval:4
target:self
selector:#selector(dropCurtain:)
userInfo:nil
repeats:NO];
[NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(askQuestion:)
userInfo:nil
repeats:NO];
}
And here's the function that gets called when the first timer is up. This doesn't run on the iPad.
-(void)dropCurtain:(NSTimer *)timer{
curtainView.hidden=NO;
//curtainView.alpha=.5;
[self.view bringSubviewToFront:curtainView];
[self.view bringSubviewToFront:triesLabel];
}
Your callback might be called not in the main thread, ui changes call only works from the main thread. If this is the case there's a method of nsobject to schedule a call to selector in the main thread, and you can call this from your callback to manipulate ui
(sorry not near my work computer)

Resources