Holding UIPIcker pauses all app timers - objective-c

i noticed that when i hold UIPicker on selection, than all my timers pauses.
I have global timer like clock which is executed every second. However when i hold picker it's pauses all timers in app stops.
Maybe some one had this problem and have a solution ?
Thank you

If your timer should be running regardless of what happens in your UI, you should be running it on a background thread.
Of course, the timer creates its own background process to do the counting. But if you created it on the main thread then maybe the callback selector would be blocked if the UI is blocked, as is the case when holding a UIPickerView.
Just start your timer on a global queue and message the UI on the main queue.

Related

iOS7 Background fetch beyond max permitted time

I'm using background fetch to periodically refresh my app content in background and sometimes it happens that I need more than 30 seconds (the max background fetch permitted time) to complete the update.
My experience is that the app gets killed by iOS watchdog and background fetch gets never called again until I reopen the app in foreground and put it in background again (https://devforums.apple.com/thread/223357, login required). For this reason I added a timer to get notified when the background time is about to end so that I can call the background fetch completion handler and avoid being killed by the watchdog.
My question is: is it acceptable to simply call the completion handler even if the operations the app was carrying on were not completed?
My understanding is that calling the completion handler puts the app in the suspended state and my running threads are frozen and resumed on the next background fetch. Am I allowed to do this or I should terminate all my running threads before calling the completion handler?
Thanks in advance

NSThread halting when lost focus

I have a a few threads that needs to run constantly or be locked at my disposal. When I lock the phone or swap applications the thread seems to halt until the application is back in focus.
I have a class Worker that is a sub class of NSThread. There is a method called start which is called by the firstViewController that creates the Worker object.
//method start
[self performSelectorInBackground:#selector(run) withObject:self];
What do I need to do to make my thread run all the time, rather than only running while in focus?
Thanks :)
When your app enters the background, all threads as suspended - unless you've configured your application to use multi-tasking, and your work is being done using the multi-tasking methods. This is detailed at Apple developer.
In short, you basically can't have a thread running constantly in the background on iOS if you want to be accepted in the App store, unless you're a navigation or VOIP application. You can have a thread continue to run for around 10 minutes after you enter the background, but that's it.

Pausing a process for a pre-set (hardcoded) period of time

I am fooling around with NSTimer in a program I am writing and am having some troubles envisioning how I can do a specific task. What I want to have happen is that I want the process I am running (a method responding to a button push) to pause for a period of time and then continue. I can get the basic timer stuff to work by creating the timer in the button push method then watching it fire off and invoking a second method. However, I am not sure how I would go about pausing the button push process that spawned the timer in the first place.
Is there a way to have the button push method wait around until the timer methods fires off and tells the button push method to 'go'? Is there a queue type entry or notification type entry that I can wait on in the button push method that would be sent by the timer selector method?
Any info would be helpful.
I think you want to pause the main thread where your logic is running. Try using
[NSThread sleepForTimeInterval: 1.0]; //pauses the thread for one second

Interrupting a loop using NSNotification

I have a class containing a method with a loop. I need to be able to break the loop if a certain event (e.g. button press) occurs.
I am using the NSNotificationCenter to notify the class containing the loop when the button is pressed.
However, If I press the button while the loop is being executed, the notification occurs after the loop is complete instead of interrupting the loop.
I'm guessing this is because it is operating in the same thread.
So how do I get the NSNotificationCenter operating in a background / different thread? Is this possible? Or is there a better way to do it?
It's not just the notification center.
I have a class containing a method with a loop. I need to be able to break the loop if a certain event (e.g. button press) occurs.
The events for that button press come in on the main thread. If your loop is running on the main thread, then the button press itself does not get processed until your loop is finished. The notification is posted immediately, relative to the button press actually getting processed by your application.
Or, in list form:
The user presses the button.
Your loop runs out of things to do and returns.
The button press arrives in your application and is turned by the button into an action message.
You post the notification.
You receive the notification.
The delay that you're seeing is between steps 1 and 2; step 4 happens immediately after step 3.
Notifications on a local (not distributed) NSNotificationCenter are dispatched on the thread you post them from, so posting it from your action method means that it will be dispatched on the main thread. This is normal and OK.
Move the loop, not the notification, to a background thread, dispatch queue, or operation queue. If you use an operation queue, you may not need the notification at all, as you can tell an operation queue to cancel all pending operations. (Your operations will need to check at any appropriate time(s) whether they have been canceled; for reasons previously discussed, killing a thread/operation at a random time is a Bad Idea.)
Background threads, blocks, and operations can communicate back to the main thread when needed (e.g., to update the UI). To send a message through the main thread's run loop, use performSelectorOnMainThread:withObject:waitUntilDone:. To dispatch a block on the main thread, use dispatch_async and dispatch_get_main_queue. To schedule an operation on the main thread, add it to [NSOperationQueue mainQueue].
For more info, read the Concurrency Programming Guide and the Notification Programming Topics.
I would run your loop in a separate thread, and have an instance variable BOOL abort;, when your button press notification comes in, set abort = TRUE; then in the loop check this value and exit if it is true.
I would run the loop in a separate thread. Even better, make it an NSOperation so that you can call [.. cancel]. Just make sure to use performSelectorOnMainThread when updating the UI from the NSOperation object. It's not a good idea to have a long running loop on the main thread.
You can't put the notification center on another thread. That object is out of your control. The problem isn't so much that they are on the same thread as that you are not allowing the run loop, which is responsible for handling the button press, to do anything. (There's one and only one run loop per thread.) As has been stated by both edsko and Peter Hosey, the button press itself, and in fact your entire UI, is stopped while your loop is running. It is generally a good idea to put long-running operations onto a background thread, then call back to the main thread to update the UI, performSelectorOnMainThread:withObject:waitUntilDone: being an easy way to do such a call back.
That said, if you were to keep the loop on the main thread, you need to let control return to the run loop periodically so that the button press will be registered. There are two ways I can think of to do this. First, you can explicitly give the run loop control briefly during each iteration of your loop:
while( !buttonWasPressed ){
// Do work...
// Let the run loop do some processing before the next iteration.
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
Or, you can make a single method that consists only of the code from your loop, and use performSelector:withObject:afterDelay: to have the method repeatedly called while still allowing the run loop to work:
- (void) loopTheLoop {
if( buttonWasPressed ) return;
// Do work...
// Run this method again as soon as possible.
[self performSelector:#selector(loopTheLoop)
withObject:nil
afterDelay:0.0];
}

Cocoa - NSThread and First Responder

When I start a 2nd background thread and pause the main thread, will my First Responder still be in action? For example I have an overwriting method called -flagsChanged and was wondering if it would still be active if the main thread is offline.
Thanks,
Kevin
Don’t pause the main thread since the main thread is responsible for handling events and your application UI will become irresponsive. If the main thread is paused, it won’t handle events, hence it won’t dispatch key events to the first responder.
If you think you need to pause the main thread, you probably need to redesign your program so that the behaviour that requires sleeping (if it does require sleeping) is offset to a secondary thread. If you need to update the user interface from a secondary thread, you should use -performSelectorOnMainThread:withObject:waitUntilDone:.