james Burns
james Burns

Reputation: 864

How to reliably sequence commands in Objective-C/iOS

I'm struggling with trying to figure something out here, and could use some pointers. Writing an app that has a web view. I want it to start out at a certain distance, find the user location, and zoom into that point, centered, and then add map annotations.

I understand the mechanics of each of these requirements, but am having problems sequencing them so they happen in order. Because of the concurrent nature of Obj-C, I can't rely on one task finishing before the next starts.

I'm looking for solutions that will allow me to do one task, upon completion, do the next, and so on. I'm thinking this will involve blocks, but I'm just learning all this, and they make my head spin.

I'd appreciate any suggestions. Thanks in advance.

Upvotes: 0

Views: 971

Answers (2)

JeremyP
JeremyP

Reputation: 86701

If you use NSOperation and NSOperationQueues you can make each individual operation have dependencies on operations that must complete first.

Edit

Here's roughly how to use operations. More information can be found in the Operation Queues section of the Concurrency Priogramming Guide. I definitely recommend you read this because I am only going to cover a tiny subset of what you can do with operations.

Firstly, create your operation(s). You can either create block operations, where you supply a block, invocation operations where you supply a Cocoa invocation or you can subclass the NSOperation class yourself and override main to do the work.

Let's say you choose block operations:

NSBlockOperation op1 = [NSBlockOperation blockOperationWithBlock: 
                          ^{
                               // Do some work.
                          }];
NSBlockOperation op2 = [NSBlockOperation blockOperationWithBlock: 
                          ^{
                               // Do some different work.
                          }];
NSBlockOperation op3 = [NSBlockOperation blockOperationWithBlock: 
                          ^{
                               // Do yet more work.
                          }];

Now, you can put these all on a queue to execute.

NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation: op1];
[opQueue addOperation: op2];
[opQueue addOperation: op3];

That will run all of the operations, possibly in parallel (depending on available system resources) unless you set the queue's maximum concurrent operation count. Let's say op3 should only be done after op1 and op2 are finished. You could set dependencies to model the relationship (before you put the operations on the queue!).

NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
[op3 addDependency: op1];
[op3 addDependency: op2];
[opQueue addOperation: op1];
[opQueue addOperation: op2];
[opQueue addOperation: op3];

Now op3 will only run after op1 and op2 have finished. The great thing about this is that you set up the dependencies and then just shove all the operations on a queue and forget about them (although adding a completion handler to op3 to tell you when they are all done might be a good idea). The operating system then takes care of balancing load against parallelisation and the sequencing you have defined.

Upvotes: 8

Darren
Darren

Reputation: 10408

One way I wait for something to finish first is put it in a sub routine that returns a BOOL: -(BOOL)myMethod { // method here Return YES; } And call it with: If (myMethod) { // what you want to do next }

Upvotes: 0

Related Questions