recurrence with performSelector after delay - objective-c

-(void)manageNetConnection{
static BOOL closing=FALSE;
NSLog(#"connecting Imap after net");
if([imapStoreObj isStoreConnected] && closing==FALSE){
[imapStoreObj close];
NSLog(#"close store");
closing=TRUE;
[self performSelector:#selector(manageNetConnection) withObject:nil afterDelay:5.0];
return;
}else if ([imapStoreObj isStoreConnected] && closing==TRUE) {
[self performSelector:#selector(manageNetConnection) withObject:nil afterDelay:5.0];
return;
}
closing=FALSE;
[indicatorForGetMail setHidden:NO];
[indicatorForGetMail startAnimation:nil];
netOff=2;
NSLog(#"netOff==%d",netOff);
[editFolderTable setAllowsMultipleSelection:NO];
NSLog(#"connect net");
[self reconnect];
}
This function is expected to call itself until connection is re-established. The problem is that the function doesn't calls itself after the specified delay.
Please help

I encountered the same issue with #performSelector. Use #performSelectorOnMainThread and NSTimer instead.
-(void)manageNetConnection{
...
[self performSelectorOnMainThread:#selector(startTimer:) withObject:#"manageNetConnection" waitUntilDone:YES];
...
}
- (void)startTimer:(NSString *)data{
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(endTimer:) userInfo:data repeats:NO];
}
- (void)endTimer:(NSTimer *)timer{
NSString *target = [timer userInfo];
SEL targetSelector = NSSelectorFromString(target);
[self performSelectorInBackground:targetSelector withObject:nil];
}

Below line will call -(void)manageNetConnection; method for once after 5.0 if your both conditions are satisfying.
[self performSelector:#selector(manageNetConnection) withObject:nil afterDelay:5.0];
Check for both if condition and else if condition satisfies.
if([imapStoreObj isStoreConnected] && closing==FALSE){
[self performSelector:#selector(manageNetConnection) withObject:nil afterDelay:5.0];
return;
}else if ([imapStoreObj isStoreConnected] && closing==TRUE) {
[self performSelector:#selector(manageNetConnection) withObject:nil afterDelay:5.0];
return;
}
or else you can use which repeats the call
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(testMethod:) userInfo:nil repeats:YES];

Related

Add continuation block to method

I have a singleton that displays status messages:
+ (FFStatusDisplay*) sharedInstance
{
static FFStatusDisplay* sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,
^{
sharedInstance = [[FFStatusDisplay alloc] init];
});
return sharedInstance;
}
- (void) showStatus:(NSString*)message Timeout:(float)timeout Controller:(UIViewController*)controller
{
if (![self isDisplaying])
{
[self setIsDisplaying:YES];
[self setStatusAlert:[UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert]];
[controller presentViewController:[self statusAlert] animated:YES completion:
^{
[NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(timerExpired:) userInfo:nil repeats:NO];
}];
}
}
- (void)timerExpired:(NSTimer *)timer
{
[[self statusAlert] dismissViewControllerAnimated:YES completion:nil];
[self setStatusAlert:nil];
[self setIsDisplaying:NO];
}
I would like to modify showStatus so that I can optionally call it with a completion block that executes after the message is removed by the timer. I think the declaration should be something like this:
- (void) showStatus:(NSString*)message Timeout:(float)timeout Controller:(UIViewController*)controller withBlock:(nullable id (^)(void))block;
But I don't know how to call the block in the body of the implementation. What I've been trying isn't right:
{
if (![self isDisplaying])
{
[self setIsDisplaying:YES];
[self setStatusAlert:[UIAlertController alertControllerWithTitle:nil message:message preferredStyle:UIAlertControllerStyleAlert]];
[controller presentViewController:[self statusAlert] animated:YES completion:
^{
[NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(timerExpired:) userInfo:nil repeats:NO];
}];
}
block; //this isn't right
}
Can someone show me how to do this?
Thanks
In Objective-C, you call a block like a C function:
block();
That being said, if you want it to fire after your timer has fired, you'll need to add some mechanism to hang onto the block and call it from your timerExpired: method

Why NSTimer doesn't stop with invalidate?

I make a Cocoa application.I create a NSTimer,it can work,but can't stop with invalidate.The following is my code.Anyone else can help me?
#implementation Document
{
NSTimeInterval elapsedTime;
NSTimer *timer;
}
- (IBAction)start:(id)sender
{
elapsedTime = 0.002f;
dispatch_async(dispatch_get_main_queue(), ^{
if(timer == nil)
{
NSLog(#"Starting");
captureFrame = [[CaptureFrame alloc] init];//captureFrame is another object
timer = [NSTimer scheduledTimerWithTimeInterval:elapsedTime target:captureFrame selector:#selector(sendSingleImageImage) userInfo:nil repeats:YES];
NSThread *thread = [NSThread currentThread];
NSLog(#"Current thread is%#",thread);// I want to see the thread.
}
else
{
NSLog(#"Exist!");
[timer invalidate];
timer = nil;
}
});
[_stopButton setEnabled:YES];
[_startButton setEnabled:NO];
}
- (IBAction)stop:(id)sender
{
dispatch_async(dispatch_get_main_queue(), ^{
[timer invalidate];
timer = nil;
NSThread *sthread = [NSThread currentThread];
NSLog(#"S thread is %#",sthread);// I want to see the thread
});
[_startcastButton setEnabled:YES];
[_stopButton setEnabled:NO];
NSLog(#"Stopping");
}
I tried use the following method,but didn't work.
dispatch_async(dispatch_get_main_queue(), ^(void)block)
I also tried to find whether two actions in the same thread,and the result is yes.
So please tell me how to stop the NSTimer.
Any help is appreciated,thanks a lot in advance.

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 to execute long running task in background

I want to execute long running task in background in Iphone but code which I using for background task executes only for 3 mins
My code is
- (void)startService{
[self startBackgroundTask];
}
- (void) startBackgroundTask{
self.backgroundDataSendTimer = [NSTimer scheduledTimerWithTimeInterval:backgroundDataSendfrequency
target:self
selector:#selector(dobackgroundDataSendInBackground)
userInfo:nil
repeats:YES];
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^
{
if ( self.backgroundTask != UIBackgroundTaskInvalid)
{
[self endBackgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
});
}];
- (void) endBackgroundTask{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
[self startBackgroundTask];
}

How to run NSTimer until flag variable ON in Cocoa

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
}