Fire method when a specific nsdate has passed - iphone

I want my App to call a method at an setter NSDate (It only needs to happen when the app is active, I'll handle passed events on launch in the app delegate).
I read about some ways to achieve such a behavior: On the one hand to work with performSelector:withObject:afterDelay: (But this doesn't look like a good way for me) or on the other hand to work with an NSTimer.
What is the best way regarding the app performance? One requirement is that you can cancel the event.

Using NSTimer is a simple solution. It has a property called fireDate that tells you when it's going to fire next. And it's a writeable property, so you can set that date to whatever you want.
Cancel the event by invalidating the timer object.

Related

iOS: multiple NSTimer instances using the same view - do I need to use multithreading?

I'm working on a multiview app. One of the views is a table view. Each cell has a stopwatch. I'm planning to use NSTimer for the stopwatches. Do I need to implement multithreading for the timers to work properly even when the user switches the view and then comes back later?
I did my research but most of the tutorials cover one NSTimer in a single view. I want to make sure the user can do other things while the timers are running, like use the interface, navigation, etc. In another post Placing an NSTimer in a separate thread someone said you need a different runloop for the timer. Would I need one runloop for each timer in my case? Is it advisable? Any performance drawbacks?
Thanks a lot!
One run loop should be just fine. Your interface will still be responsive.
Keep in mind that timers are never guaranteed to be accurate. They are affected by how much other stuff is on the same loop. Its ok to use the timer to update the display but not to actually measure time. Set an NSDate when you start a stop watch then compare the current date with that start date each time your display timer updates the display.
Since you should only use the NSTimer to update the display, could you just use one generic display update timer that updates all running stopwatches, instead of having one for each stopwatch?

How to keep NSTimer alive?

I have 2 viewControllers in my app, from first view when i navigate to next one there is a button named startTimer with a timer action as selector method on Click of startTimer the timer starts up in HH:mm:ss format, i am not invalidating timer,but When i go back to 1st viewController and again if i come to again 2nd viewController and if i press startTimer button the timer again starts from 0, but i want it to be retained the previous value,how can i achieve this? i know that since i'm loading again the viewController the nib will be loaded freshly to memory but how can i retain the timer label and timer value?
Any help is appreciated in advance.thank you.
You've broken MVC (Model-View-Controller) by putting your data into your view controller. Moreover, you're asking a mechanism with no solid promises about time (NSTimer) to keep track of time for you. NSTimer does not fire exactly at the interval you request. It can fire at any arbitrary point after that interval. Using NSTimer as a stopwatch will almost always lose time (sometimes quite a lot of time, particularly if there's a scrollview around). (That last bit is overstated. A repeating timer schedules itself correctly so won't usually lose time. You'll just lose time if a repeat is completely skipped, which can happen during long scrolls or other things that can keep timers for firing for a full second.)
Create a new model object to hold the stopwatch information. Let's call it Stopwatch. Assuming you need it to be startable and stoppable, it needs an NSTimeInterval accumulatedTime property and an NSDate lastStarted property (you could also make lastStarted an NSTimeInterval if you like). So to start the stopwatch, you set lastStarted to "now." To stop the stopwatch, you clear lastStarted and move the current accumulated time to accumulatedTime. To find out the current time, you add accumulatedTime to now - lastStarted.
OK, now that you have that, what can you do with it? You can pass it to your view controllers and they can ask "what's the current stopwatch value?" They can start and stop it as they like.
Now your view controller would like to update its display every second, so you have a timer that does that. Every second it asks the stopwatch, "what's the current time" and it displays it. But it does not set the time. It just asks.
BTW, you can also use KVO on Stopwatch, but it's a little trickier, since Stopwatch needs to run its own timer to send out the change notifications. I generally find this more trouble than its worth.
Don't do like that, this way every time you load the view containing the NSTimer, a new NSTimer object is created and the old one is still in the memory since you're not invalidating it.
The best way is that you must put NSTimer in the Application Delegate and then start it only when you first time load that View Controller.
For achieving this, you must put a flag to check that the View is loaded first time or not.
If the NSTimer is one of your instance variable, I guess you could do a check to see if it is allocated or not.
//NSTimer *timer; declare this in your interface
if (timer==nil)
{
// allocate timer
}
//Do nothing if it is allocated all ready
What I would do is to mantain the second view controller as an ivar of your first view controller. This way, you can instantiate it just once and your NSTimer will remain in memory.
However, if you want to maintain your style, you should save the current time in any kind of preferences (look at [NSUserDefaults standardUserDefaults] or create your own singleton class). Then in view did load method from your second view controller, load that value and add it as an offset for your timer.
Hope to help!

How to schedule events programmatically in ios?

I have been tasked to write an app that allows a user to schedule emails to be sent out in future.
The user selects a date time from a date picker, composes the message and recipient and then schedules the event. When the date/time occurs the message is sent out.
Can someone guide me to how to get about scheduling lets say a text message. I know how to send a text message. Just was not sure on the scheduling aspect of things.
Any pointers will be much appreciated.
The first response will technically allow you to establish a timer that will fire every 2.5 seconds, however the original poster asked for a solution that would fire at a specific time. For that you need to use the following method of NSTimer:
- (id)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
The first argument is an NSDate indicating when the timer should fire.
The original poster did not specify, but if this is an iOS app then it is important to understand that timers scheduled to fire at a distant date/time will not fire if your app is not the foreground app. In fact there is no way to schedule such an event to occur when your app is in the background on iOS, so you must take that into account.
Here's a snippet of code which sets a one use timer to call self's imageSavedLabelOff: selector with itself (the timer) as the object parameter to the method. The timer schedules the call to be made in 2.5 seconds.
NSTimer *quickie = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(imageSavedLabelOff:) userInfo:nil repeats:NO];
You may have already found the answer by now but for future visiters like me I would like to suggest an answer- i.e. EventKit :
https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/EventKitProgGuide/ReadingAndWritingEvents.html
You can schedule/fetch events for any time and do your stuff accordingly. Hope this helps somebody.
You should be able to achieve this using NSRunLoop. Check out the Threading Programming Guide.
Apart from the use of NSTimer, you should be aware that sending of the E-Mail can fail for several reasons (no network available and others). Then you need to reschedule the request, maybe give up after 3 retries and notify the user about this.
You can use -
[self performSelector:#selector(myFunc:) withObject:nil afterDelay:5.0];

Having issues with iPhone NSTimer invalidation

Okay so I know I asked a similar question a while ago, but this is different. I now have two timers that go off on the TouchDown event of their respective buttons. On the TouchUpInside event I have respective code that tells each timer to [pressTimer invalidate] and pressTimer = nil. The problem that happens now since I added the second timer is that when the selector is triggered (thus releasing the button and triggering the TouchUpInside event) the app crashes and spits out an Not recognized [NSCFTimer -invalidate] or something like that. The buttons work normally, until the timer triggers, and even then no crash until I let up my finger. I think what's going on is that the TouchUpInside event is trying to invalidate an invalid/triggered timer, because it works fine while the timer is still running. I wonder why this is happening since it never happened before I added the second timer. My temporary fix is to set the repeating:YES portion of the timer, which supports my theory that it can't invalidate an invalid/triggered timer. Any suggestions?
*Bonus: On a related note, how many crashes do I need to get from people before they show up in iTunes Connect?
For one thing, the pressTimer=nil serves no purpose; nil assignment only releases objects when using a setter, on a retained property, i.e. self.timer = nil;. (this actually does: [self setTimer:nil]!)
But even then, if you misquoted yourself and did use a setter, an NSTimer instance need not be released, it only needs to be invalidated. Your "kind of quoted" error should not happen.
As for you theory: you may read invalidate as release in this context - you can't do it too often...
The manual states that invalidate needs to be called from the same thread where it was installed, beyond that there's really no reason for anything to crash.

awakeFromNib opposite?

Is there a reverse of awakeFromNib, a method called when the nib is closed? I know an application delegates receive a notification the the application will terminate, but was wondering if there was to save some state information on a simple NSObject.
Not really, but mostly because it generally doesn't make sense. By the time an individual object is being deallocated, it is generally too late to do anything meaningful.
For saving state, you would generally want to do so periodically, often triggered by some user action (user just entered a bunch of data.... good time to save, user transitioned to a new part of the app.... save). Only saving as the app is terminated or as a window is closed (or, in your case, as a particular screen is exited) is a recipe for data loss.
For an NSObject instance its dealloc routine will get called as the object is going away -- you should have a chance there to save off any state you need to before destroying self and super.