mm24
mm24

Reputation: 9606

iOS: Repeated task only when APP is active (No background)

I have found several post asking how to run background tasks. This is fine. I get it. There is a guideline from Apple and can be done only for certain types of Apps.

My use case here is the following: I want to update the contact list of a chat App only when the APP is in foreground. Hence I can start/pause/resume when the App goes respectively in the following states: didBegan, didEnterBackground, didResumeFromBackground.

How can I achieve this using GCD?

In other words, how can I schedule an asynchrounous task in a repeated way and to be called only every so often (say every 0.5 seconds)? Is there a good implementation using NSOperationQueue?

EDIT 2: Tasks I want to perform:

1: GET from a webservice API a JSON data object containing information on the contacts (online status, device, lastseen at)

2: GET from a webservice API a JSON data object containing messages to the user

EDIT: NSOperation documentation defines an operation as something that can be used only as "single shot", hence creating a recursive operation is probably not the best way to solve this.

Upvotes: 0

Views: 961

Answers (2)

Léo Natan
Léo Natan

Reputation: 57060

Here is some code on how to achieve this with a timer and both GCD and an operation queue.

NSOperationQueue* queue = [NSOperationQueue new];
[queue setMaxConcurrentOperationCount:1]; //Make serial.
//dispatch_queue_t queue = dispatch_queue_create("queue", NULL); //Serial queue.

Gentlemen, start your timers:

[NSTimer scheduledTimerWithTimeInterval:0.0 target:appDelegate selector:@selector(timerTicked:) userInfo:nil repeats:NO]; //Start a timer with 0 so it ticks immediately.

Now in the method:

- (void)timerTicked:(NSTimer*)timer
{
    NSLog(@"Timer ticked!");
    void (^block)() = ^{
        //Do what you need here.

        //Start a new timer.
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:appDelegate selector:@selector(timerTicked:) userInfo:nil repeats:NO];
    };

    [queue addOperationWithBlock:block];
    //dispatch_async(queue, block);
}

I use the app delegate because timers retain the target object, so I don't want to have it in a view controller. You can schedule the next timer either right after timer tick or after the operation/task has completed, which is what I prefer to do.

Upvotes: 5

jsd
jsd

Reputation: 7703

Use NSTimer to schedule a timer that fires every .5 seconds. It could add your NSOperation to an NSOperationQueue. You might want to make a special queue with a max concurrency of 1, so it will only run one of your things at a time. You might also want to cancel all previous operations when adding a new one, just in case things start to 'pile up'. I don't know what your specific task is so it's hard to be more precise.

Upvotes: 1

Related Questions