0
votes

I have an app that needs to synchronize multiple entity types with a backend using an API.

To do that I created a subclass of NSOperation for each HTTP method (GET/POST/PUT/DELETE => 4 operations). For a given entity these operations have to be run in a specific order, so I created a 5th operation subclass which contains the synchronization sequence (basically an operation that creates multiple GET/POST/PUT/DELETE operations in the appropriate order and adds these operations to a queue created by the operation.).

Since i want to be able to synchronize multiple kind of entities (for example 'Users' / 'Events' / 'Tasks') at the same time depending on the connection of the user and with dependencies between some types of entities (for example i need to finish the 'Users' synchronization before i can start concurrently the 'Events' and 'Tasks' synchronizations) I use a NSOperationQueue that contains only NSOperations of type synchronization.

So just to sum up, if I made 1 change of each type (1 create, 1 update, ...) on each type of object, and that i want to synchronize everything. I'll have 1 NSOperationQueue that will contain 3 NSOperations (1 for each type of object), and each NSOperation will have its own NSOperationQueue that should run 4 NSOperation (1 for each change type).

Now comes the problems :

1st/ The "sub-operations" are using async NSURLConnection, and I don't know how should the NSURLConnection be configured ?

Should i use something like this :

    connection = [[NSURLConnection alloc] initWithRequest: theRequest delegate: self startImmediately: NO];
    NSRunLoop * currentRunLoop = [NSRunLoop currentRunLoop];
    [currentRunLoop addPort: [NSPort port] forMode: NSDefaultRunLoopMode];

    [connection scheduleInRunLoop: currentRunLoop forMode: NSDefaultRunLoopMode];
    [connection start];
    [currentRunLoop run];

Or should i use that :

while (!finished)
{
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

2nd/ At the moment i am overriding start for the operations because i want to be able to start them without using an NSOperationQueue when I have only 1 operation. Is it correct ? If yes, are there examples somewhere of start method implementations ?

3nd/ About the runloops and threads, each operation will always get a different runloop and thread ? And this thread / runloop management must be handled in the start method if i override it ?

4th/ is it a problem to use queue like I do (i think it's justified in my case) ?

1

1 Answers

0
votes

1) I tend to use the synchronous request when running in the background. I find it's cleaner and you're in the background already anyways.

2) Subclassing NSOperation in my opinion is not flexible and creates sort of sloppy code. Instead I would suggest keeping some sort of services class that has an NSOperationQueue and from there use the [NSOperationQueue addOperationWithBlock:]. You can even take it a step further if you want and create an NSBlockOperation. The main thing you gain from this API is the ability to have a completion block. But i find that keeping the services layer and the operations (in this case in the form of blocks) easier to manage and understand. You can even create functions that return blocks so the blocks can be reused how ever you need. This may help you to have better code reuse than subclassing NSOperation Example:

-(void)foo
{
   __weak ClassName wself = self;
    void(^opBlock)() = ^{ [wself doStuff]; };
    [_queue addOperationWithBlock:opBlock]
}

3) Yes your queue will have its own run loop.

4) Maybe refer to the others