I am trying to use a timer to fire the onTick method once after a 0.5 second delay using the following Objective C code in Xcode for a MacOS target
[NSTimer scheduledTimerWithTimeInterval:0.5
target: self
selector:#selector(onTick:)
userInfo:nil repeats:NO];
...
-(void) onTick
{
}
But the selector onTick never fires. The code is in AppDelegate.m and is running on the main thread. What am I doing wrong?
Change
#selector(onTick:)
to
#selector(onTick)
(notice the deleted colon).
Related
So I am using NSTimer to run a function every minute, it fires at the correct time for the first 3 or so attempts and then it suddenly starts firing every second. I have no idea why this is happening? Would anyone be able to let me know as to why NSTimer is firing inconsistently?
Here is the line where I have declared my timer.
[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:#selector(checkForLocation) userInfo:nil repeats:YES];
It is worth noting that I have NSTimer declared inside of viewDidAppear.
Any help is appreciated,
Thank you.
Try to create a instance for NSTimer by declaring a property. Write a function which will initialize the timer and don’t forget to invalidate it before re-intializing it. Call initializeMyTimer in your -viewDidAppear.
-(void) initializeMyTimer
{
if(myTimer)
{
[myTimer invalidate];
myTimer = nil;
}
myTimer = [NSTimer scheduledTimerWithTimeInterval:60.0f
target:self
selector:#selector(checkForLocation)
userInfo:nil
repeats:YES];
}
I have a button and want to fire it automatically by itself without touch.
Is it possible?
-(IBAction)xxx:(id)sender
My answer assumes you have the method:
- (IBAction)someAction:(UIButton *)sender {
}
and that you have a reference to the button in an instance variable named someButton.
If you just need to "fire it" now, simply call it:
[self someAction:someButton];
If you need to "fire it" once, but later, you can do:
// call it 5 seconds from now
[self performSelector:#selector(someAction:) withObject:someButton afterDelay:5.0];
If you want to fire it repeatedly, use a timer:
myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(buttonTimerFired) userInfo:nil repeats:YES];
- (void)buttonTimerFired {
[self someAction:someButton];
}
Action can be called like every regular function - you can do it by running a timer on something else.
You should use NSTimer for doing your work.
[NSTimer scheduledTimerWithTimeInterval: 0.01f target: self selector: #selector(BtoonMethod) userInfo: nil repeats: NO];
-(void)BtoonMethod
{
// write code for call yor button method
}
In my iOS application I have registered the AppDelegate as notification listener for CoreData changes. With this piece of code:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(mergeChangesFromContextDidSaveNotification:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:[self persistentStoreCoordinator]];
And the mergeChangesFromContextDidSaveNotification method get correctly called every time there's an update.
However inside this method I am trying to call an NSTimer for doing another operation:
- (void)mergeChangesFromContextDidSaveNotification:(NSNotification *)notification {
NSTimer *t =[NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(mergeCoreDataFromCloud:)
userInfo:nil
repeats:NO];
}
}
and the point is that mergeCoreDataFromCloud: which should be fired by the timer is never called. This is the signature:
-(void)mergeCoreDataFromCloud:(NSTimer*)timer {
// never called...
}
please note that I am at early stage of development, the code is not perfect, and I am only interested in knowing why the timer is not started.
I suppose it has something to do with threads, but I have no guess...
thanks
A timer relies on the run loop being run in the mode(s) in which it has been scheduled.
In a Cocoa app, the main thread runs its run loop automatically. However, no other thread can be relied on to run its run loop automatically.
So, usually you want to schedule timers on the main thread. You can also schedule them on a thread you create and control, which you cause to run its run loop in an appropriate mode.
There's no enough information in your question to know what thread this code is being called on.
You could be right about the thread issue -- it that's the case, then I think you have to use an unscheduled timer and add it to the run loop manually. Try this, and see if it works:
NSTimer *t = [NSTimer timerWithTimeInterval:10 target:self selector:#selector(mergeCoreDataFromCloud:) userInfo:nil repeats:NO];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:t forMode:NSDefaultRunLoopMode];
I'm trying to debug my application.
I've been using some NSTimer instances in my non-arc code like this (from the main thread):
[NSTimer scheduledTimerWithTimeInterval:5 target:musicPlayer selector:#selector(playPause:) userInfo:nil repeats:NO];
This works fine if I assign this code to a button and click a button. The timer fires.
I've also tried:
if( self.deliveryTimer == nil)
{
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(playPause:) userInfo:nil repeats:NO];
}
-(void)playPause:(NSTimer*)timer
{
[deliveryTimer invalidate];
deliveryTimer = nil;
//more code here
}
I would expect the timer to execute, hit the play/pause method below, then turn to nil, so I can reset the timer later. The reason why I'm checking for nil is because I have 3 different code paths that may set the timer. Each one has an NSLog statement indicating that the timer has been scheduled.
My code runs, and I see that the timers are being scheduled, but they don't seem to fire in the course of normal app execution. I'm investigating why. Short term timers, using the same logic fire fine. It is when I let the app run for a while that I'm running into issues.
Could the NSTimers be reclaimed by ARC?
Does it matter if I set the timer from a performSelectorInBackground? As I was writing up this question, I noticed that some of my timers were created from a code path that is being called through:
[self performSelectorInBackground:#selector(notifyDelegateOfDataPoint:) withObject:data];
could the background selector be the reason why my timers do not fire/get reclaimed earlier?
Any help is appreciated, this bug has been bugging me for over 2 weeks!
Update: after changing the code to use the main thread for NSTimers, the timers fire correctly, causing the music to play:
[self performSelectorOnMainThread:#selector(deliverReminder:) withObject:nil waitUntilDone:NO];
-(void)deliverReminder:(id)sender{
[ NSTimer scheduledTimerWithTimeInterval:10 target:reminderDeliverySystem selector:#selector(playAfterDelay:) userInfo:nil repeats:NO];
[self postMessageWithTitle:nil message:#"Deliver Reminder Called" action:kNoContextAction];
}
-(void)playAfterDelay:(id)sender
{
int reminderDelay = reminder.delayValue.intValue;
[playTimers addObject:[NSTimer scheduledTimerWithTimeInterval:reminderDelay target:self selector:#selector(appMusicPlayerPlay:) userInfo:nil repeats:NO]];
}
Here I have a whole bunch of timers, which is because I don't know how to pass a primitive to a target with a selector.
An NSTimer requires a run loop to be running in that background thread for it to keep firing. The main thread already has an active run loop, which is why your timers work fine when executed on it.
If you want to use your timers within a background thread, you can do something like the following:
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(playPause:) userInfo:nil repeats:NO];
[runLoop run];
What was probably happening with your short duration timers firing, but the longer ones not, was that they were firing while the thread was still active, but without a run loop to keep it going, were failing after the thread reached the end of its execution.
I don't believe this is ARC-related, although there may be something there you'll have to watch for, because the NSRunLoop holds on to a timer that is attached to it. Following standard procedure with NSTimers should avoid ARC problems.
How do I trigger a delay, let's say I want to call a method (once) in 3 seconds from now, and how do I cancel that call if I need to?
You can also use -[NSObject performSelector:awithObject:afterDelay:], and +[NSObject cancelPreviousPerformRequestsWithTarget:selector:object].
Use NSTimer. Use this to set up a call to method in three seconds time. It will only be called once:
[NSTimer scheduledTimerWithTimeInterval: 3
target: self
selector: #selector(method:)
userInfo: nil
repeats: NO];
method needs to look like this:
- (void) method: (NSTimer*) theTimer;
You can pass parameters into the method using userInfo (set to nil in the above example). It can be accessed in the method as [theTimer userInfo].
Use the invalidate method on NSTimer to cancel it.
in your header..
NSTimer *timer;
when you want to setup..
timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(yourMethod:) userInfo:nil repeats:NO];
when you want to cancel..
[timer invalidate];