How to run NSTimer until flag variable ON in Cocoa - objective-c

I have a problem: I want to NSTimer waiting until FLAG variable is YES, if FLAG = YES, myTimer is stop. How can i do that? I tried below code:
NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:#selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer timerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
[[NSApplication sharedApplication] runModalForWindow: scanningPanel];
This is resetAll () function :
-(void) resetAll: (NSTimer *) theTimer
{
if(FLAG)
{
NSLog(#"killWindow");
[[NSApplication sharedApplication] abortModal];
[scanningPanel orderOut: nil];
FLAG = NO;
}
else
{
delay +=6.0;
myTimer= [NSTimer timerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
[[NSApplication sharedApplication] runModalForWindow: scanningPanel];
}
}
I used 2 NSTimer, but only myTimer run, scanTimer not run. Please give me any suggestions. Thanks in advance

Why not use Key Value Observing for the FLAG change? Add the flag variable as a property of the class you're working in:
#property(nonatomic, assign) BOOL flag;
To avoid repetition place in your .m:
#define kFooFlagKey #"flag"
Override -setFlag: so it is KVO compliant:
-(void)setFlag:(BOOL)flag
{
if (_flag == flag) {
return;
}
[self willChangeValueForKey:kFooFlagKey];
_flag = flag;
[self didChangeValueForKey:kFooFlagKey];
}
In the class' initializer add self as the observer for the keypath you'd like to monitor. In this case it will be for the property "flag".
[self addObserver:self
forKeyPath:kFooFlagKey
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:NULL];
Don't forget to remove the observer in the class' -dealloc:
[self removeObserver:self forKeyPath:kFooFlagKey];
Create the timer to fire repeatedly (firingCallBack is a method called with each fire):
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.0f
target:self
selector:#selector(firingCallBack)
userInfo:nil
repeats:YES];
Implement KVO observing method:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:kFooFlagKey]) {
if (self.flag) {
[self performSelector:#selector(resetAll) withObject:nil afterDelay:0.0f];
}
}
}
Implement -resetAll however you'd like. It will be called when you are setting the flag variable via the accessor AND the flag is set to YES

Try like this:-
NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:#selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[NSApp beginSheet:scanningPanel modalForWindow:[self window]
modalDelegate:self
didEndSelector:nil
contextInfo:self];
- (void)resetAll:(NSTimer *)theTimer
{
if (flag== YES)
{
[NSApp endSheet:scanningPanel];
[scanningPanel orderOut:self];
flag=NO;
}
else
{
delay +=6.0;
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[NSApp beginSheet:scanningPanel modalForWindow:[self window]
modalDelegate:self
didEndSelector:nil
contextInfo:self];
}
}

You just start the timer (already scheduled) and make it repeat at a relatively high frequency and stop it when the condition is met. One timer can act as two, like this:
- (void)startTimers {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
}
- (void)timerFired:(NSTimer *)timer {
if (self.stopTimerA && self.stopTimerB) {
[timer invalidate];
} else {
if (!self.stopTimerA)
[self timerAFired];
if (!self.stopTimerB)
[self timerBFired];
}
}
- (void)timerAFired {
// this can be coded like it has it's own timer
// we didn't pass the timer, so we can't invalidate it
// to stop...
self.stopTimerA = YES;
}
- (void)timerBFired {
// same idea here
}

Related

Duplicate declaration of method viewDidAppear and startTimerMethod

i am trying to use this code multiple times for different view controllers however i keep on getting the same error .Duplicate declaration of method viewDidAppear and Duplicate declaration of method startTimerMethod . Can you please tell me how to fix this ASAP . thank you in advance .
the code is here
- (void)viewDidAppear:(BOOL)animated {
[self startTimerMethod];
}
- (void) startTimerMethod {
transitionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(transitionView) userInfo:nil repeats:NO];
}
- (void) transitionView {
[self performSegueWithIdentifier:#"viewTransition" sender:self];
}
- (void)viewDidAppear:(BOOL)animated {
[self startTimerMethod];
}
- (void) startTimerMethod {
transitionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(transitionView2) userInfo:nil repeats:NO];
}
- (void) transitionView2 {
[self performSegueWithIdentifier:#"viewTransition2" sender:self];
}
Just delete these below three method one time which you have declared two times-
- (void) startTimerMethod {
transitionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(transitionView) userInfo:nil repeats:NO];
}
- (void) transitionView {
[self performSegueWithIdentifier:#"viewTransition" sender:self];
}
- (void)viewDidAppear:(BOOL)animated {
[self startTimerMethod];
}

How can I produce a blinking label

I want a label to be shown for 0.4 seconds and then hidden for 0.8 seconds - in an infinite loop.
How can I pull that off?
NSTimer and UIViews hidden property would be one possibility
I would say to use NSTimer. You could do it the following way:
Say your label is myLabel:
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
You should create a method to be called by NSTimer:
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE; //change comparassion to assing
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
else
{
self.myLabel.hidden = TRUE;
[NSTimer scheduledTimerWithTimeInterval:0.8
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
}
And initialize NSTimer somewhere like so:
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
Note that you could also do the following:
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
}
else
{
self.myLabel.hidden = TRUE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.8];
}
}
Something Like the below.
In viewDidLoad:
NSTimer *silly = [NSTimer timerWithTimeInterval:0.4 target:self selector:#selector(question) userInfo:nil repeats:YES];
Function
-(void)question {
if(label.isHidden){
label.hidden = false;
} else {
label.hidden = true;
}
}
Make sure you have a UILabel defined in scope of this function and it should work. UNTESTED.

Using NSTimer, calling two functions with the same name, different parameters, both use scheduledTimerWithTimeInterval

I'm trying to write my own fade-ins and fade-outs using the AVAudioPlayer as a helper.
My problem is this: I have two method definitions with the same name, but one takes an int and the other takes no parameters. Is there a way for me to tell NSTimer which one to call? Couldn't really make sense of the documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nstimer_Class/Reference/NSTimer.html
-(void) stopWithFadeOut
{
if (_player.volume > 0.1) {
[self adjustVolume:-.1];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(stopWithFadeOut) userInfo:NULL repeats:NO];
}
else {
[self stop];
}
}
and
-(void) stopWithFadeOut:(NSString *)speed
{
int incr = [speed intValue];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(stopWithFadeOut) userInfo:NULL repeats:NO];
}
else {
[self stop];
}
}
Those actually have different names. The colon is significant, so the name (and hence the argument to #selector()) of the second method is stopWithFadeOut:.*
To create the timer, then, you want:
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(stopWithFadeOut:)
userInfo:NULL //^ Note! Colon!
repeats:NO];
However, this method is incorrect, because an NSTimer passes itself to its action method; it's not possible for you to pass in an arbitrary object. This is what the userInfo: parameter is for. You can sort of attach some object to the timer, and retrieve it inside the action method using the userInfo method, like so:
- (void)stopWithFadeOut: (NSTimer *)tim
{
NSString * speed = [tim userInfo];
int incr = [speed intValue];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(stopWithFadeOut:)
userInfo:speed
repeats:NO];
}
(Also note that this means your first method isn't really a correct NSTimer action method, because it doesn't have the NSTimer parameter.)
*The compiler wouldn't have let you declare or define two methods with the same name in one class, and the parameter type doesn't count as part of the selector, so trying to create -(void)dumblethwaite:(int)circumstance; and -(void)dumblethwaite:(NSString *)jinxopotamus; in one class doesn't work.
So this is what I came up with. Thanks Josh.
-(void) pauseWithFadeOut
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:0.1];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
}
-(void)fadeOut: (NSTimer*) deleg
{
int incr = (int) [deleg userInfo];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
}
}
-(void) pauseWithFadeOut:(NSString *)speed
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:[speed floatValue]];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
[self pause];
}
-(void) stopWithFadeOut
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:0.1];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
}
-(void) stopWithFadeOut:(NSString *)speed
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:[speed floatValue]];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
[self stop];
}

Trouble with NSTimer

I am having so much trouble with NSTimers. I have used them before, but this timer just does not want to fire.
-(void) enqueueRecordingProcess
{
NSLog(#"made it!");
NSTimer *time2 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(warnForRecording) userInfo:nil repeats:YES];
}
-(void) warnForRecording
{
NSLog(#"timer ticked!");
if (trv > 0) {
NSLog(#"Starting Recording in %i seconds.", trv);
}
}
I don't see why this won't run. I even tried this:
- (void)enqueueRecordingProcess
{
NSLog(#"made it!");
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(warnForRecording) userInfo:nil repeats:YES];
}
- (void)warnForRecording
{
NSLog(#"timer ticked!");
}
What is wrong?
Not sure if this fixes it but from the docs:
The message to send to target when the timer fires. The selector must have the following signature:
- (void)timerFireMethod:(NSTimer*)theTimer
The timer passes itself as the argument to this method.
I am not sure about you specifics, but you need to service the runloop in order to get events, including timers.
// Yes. Here is sample code (tested on OS X 10.8.4, command-line).
// Using ARC:
// $ cc -o timer timer.m -fobjc-arc -framework Foundation
// $ ./timer
//
#include <Foundation/Foundation.h>
#interface MyClass : NSObject
#property NSTimer *timer;
-(id)init;
-(void)onTick:(NSTimer *)aTimer;
#end
#implementation MyClass
-(id)init {
id newInstance = [super init];
if (newInstance) {
NSLog(#"Creating timer...");
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(onTick:)
userInfo:nil
repeats:YES];
}
return newInstance;
}
-(void)onTick:(NSTimer *)aTimer {
NSLog(#"Tick");
}
#end
int main() {
#autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}

Why does this NSTimer crash?

http://www.youtube.com/watch?v=5al6qqRzzQg when i click on the start more than once???
what will i need to do
#import "FirstViewController.h"
#implementation FirstViewController
-(IBAction)start;{
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop;{
[myticker invalidate];
}
-(IBAction)reset;{
time.text = #"0";
}
-(void)showActivity;{
int currentTime = [time.text intValue];
int newTime = currentTime + 1;
time.text = [NSString stringWithFormat:#"%d", newTime];
}
- (void)didReceiveMemoryWarning
Change your start and stop methods to this:
-(IBAction)start;{
[myticker invalidate];
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop;{
[myticker invalidate];
myticker = nil;
}
That will stop it crashing. Also, you should add this:
-(void)dealloc
{
[myticker invalidate];
}
add a bool variable to the header of your class, like timerIsActive
-(IBAction)start;{
if (!timerIsActive) {
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
timerIsActive = YES;
}
}
-(IBAction)stop;{
timerIsActive = NO;
[myticker invalidate];
}