0

I'm writing an app where I've got a long running server-syncronization task running in the background, and I'd like to use NSOperation and NSOperationQueue for this. I'm leaning this way, since I need to ensure only one synchronisation operation is running at once.

My question arises since my architecture is built around NSNotifications; my synchronisation logic proceeds based on these notifications. From what I can see, NSOperation logic needs to be packed into the main method. So what I'm wondering is if there is any way to have an NSOperation finish when a certain notification is received. I suspect this is not the case, since I haven't stumbled upon any examples of this usage, but I figured I'd ask the gurus in here. Does an NSOperation just finish when the end of the main method is reached?

Darren Black
  • 1,030
  • 1
  • 9
  • 28
  • What do you mean by "have an NSOperation finish when a certain notification is received"? Do you want to call `-cancel` to stop the operation from the outside or do you want the NSOperation to internally set it's status to `finished`. – Jeffery Thomas Mar 05 '15 at 11:32
  • I suppose either would do, but I'm really looking for the NSOperation to internally set it's status to finished. – Darren Black Mar 05 '15 at 11:37

2 Answers2

2

There is no reason a NSOperation cannot listen for a notification on the main thread, but either the finish logic must be thread safe, or the operation must keep track of its current thread.

I would recommend a different approach. Subclass NSOperation to support a method like -finishWithNotification: Have a queue manager that listens for the notification. It can iterate through its operations finishing any operations which respond to -finishWithNotification:.

- (void)handleFinishNotification:(NSNotification *)notification
{
    for (NSOperation *operation in self.notificationQueue) {
        if ([operation isKindOfClass:[MYOperation class]]) {
            dispatch_async(self.notificationQueue.underlyingQueue), ^{
                MYOperation *myOperation = (MYOperation *)operation;
                [myOperation finishWithNotification:notification];
            });
        }
    }
}
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117
1

If I understood you correctly concurrent NSOperation is what you need.

Concurrent NSOperation are suitable for long running background/async tasks.

NSOperation Documentation

See: Subclassing Notes & Operation Dependencies Section

EDIT:(Adding more explanation)

Basically concurrent operations do not finish when main method finishes. Actually what concurrent operation mean is that the control will return to calling code before the actual operation finishes. The typical tasks that are done in start method of concurrent operation are: Mark operation as executing, start the async work(e.g. NSURLConnection async call) or spawn a new thread which will perform bulk of the task. And RETURN.

When the async task finishes mark the operation as finished.

Taha Samad
  • 1,135
  • 1
  • 9
  • 22
  • I'm aware that NSOperation has some of the properties that suit my goal... but I'm not sure that it can fulfil them with the architectural requirements I have. I want to be able to end the task on an NSNotification. Not the completion of some code contained within the main method... Unless I suppose I have the main method spin the runloop indefinitely. That seems like a bit of a kludge. – Darren Black Mar 05 '15 at 11:35
  • 1
    See the Edit, I have added more explanation. In concurrent NSOperation you do not override main method. You typically override:start, asynchronous, executing, finished. And unlike non-concurrent operation your operation will not be finished when code returns from start method. Actually it is up to you when it finishes. So in your case inside start method you will do following: update appropriate variables to reflect executing state. Add observer for notification and RETURN. Now when notification is received you handle that and then update your state variable to reflect finished state. – Taha Samad Mar 05 '15 at 11:49
  • 1
    Just adding for sake of completeness, your NSOperation subclass should be KVO compliant for certain properties. See 'KVO-Compliant Properties' section. Since state(executing, finished) is managed by your code it is your responsibility to make class KVO compliant for these properties. – Taha Samad Mar 05 '15 at 11:53