5

I am currently using GCD. However, I've heard that NSOperation is actually a higher level program. It's far more complex though.

In GCD, do something at background is simply use this helper function I created:

+(void)doForeGround:(void (^)())block
{
    dispatch_async(dispatch_get_main_queue(), ^{
        block();
    });
}

+(void)doBackground:(void (^)())block
{

    //DISPATCH_QUEUE_PRIORITY_HIGH
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
    //dispatch_async(dispatch_get_global_queue(-2,0), ^{
        block();
    });
}

-(void)doBackGround:(void (^)())block onComletion:(void (^)())onCompletion
{
    [BGHPTools doBackground:^{
        block();
        [BGHPTools doForeGround:^{
            onCompletion();
        }];
    }];
}

Will doing it with NSOperation be simpler?

Am I missing something? How would I do the same thing at NSoperation?

Rob
  • 415,655
  • 72
  • 787
  • 1,044
Anonymous White
  • 2,149
  • 3
  • 20
  • 27

2 Answers2

6

You can do similar things with NSOperation as you're doing with GCD. The main difference is that NSOperation provides additional functionality.

For example:

  • NSOperation has a -cancel method. Dispatch queues have no concept of cancellation; all blocks enqueued on a queue will run to completion.
  • NSOperationQueue has a maximumConcurrentOperationCount property, which you can use (for example) to only allow 3 operations to run at a time. Dispatch queues have no such concept; they are either serial, allowing only 1 block at a time, or concurrent, allowing as many as libdispatch thinks advisable based on CPU usage and availability.
  • An NSOperation can have a dependency on other NSOperations, allowing you to defer execution of a particular operation until all of its dependencies have run. Other operations will be allowed to "jump ahead" in the queue while the dependent operation is waiting. Dispatch queues are always dequeued in strictly FIFO order. (You can somewhat imitate dependencies using the dispatch_group API, but that's really targeted at a different kind of problem.)

Now, if you're not using any of those features, GCD works just fine. There's nothing wrong with using GCD, per se. It's just that NSOperation provides a convenient wrapper for some additional nice features.

Here's how you'd rewrite your examples above using NSOperationQueue:

+(void)doForeground:(void (^)())block
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        NSLog(@"I'm running on the main thread!");
        block();
    }];
}

+(void)doBackground:(void (^)())block
{
    // Note; rather than allocating a new NSOperationQueue every time, you could
    // allocate the queue once and just refer to that queue. For simplicity, I'll
    // skip that here.
    [[NSOperationQueue new] addOperationWithBlock:^{
        NSLog(@"I'm running asynchronously on whatever thread NSOperationQueue wants!");
        block();
    }];
}

-(void)doBackground:(void (^)())block onCompletion:(void (^)())onCompletion
{
    [[NSOperationQueue new] addOperationWithBlock:^{
        block();
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            onCompletion();
        }];
    }];
}
BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • And I suppose NSOperation also create their own nested autorelease stacks? – Anonymous White Oct 19 '12 at 04:19
  • https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html doesn't describe a method called new. Ah it must be that shortcut for alloc]init] – Anonymous White Oct 19 '12 at 04:23
  • `+new` is inherited from `NSObject`, just like alloc and init. And yes, each operation's block will live in an autorelease pool. – BJ Homer Oct 19 '12 at 06:10
  • Awesome... Thanks a lot. Yes now you do it this way it makes a lot of sense. The documentation of NSOperation doesn't make sense at all. – Anonymous White Oct 19 '12 at 06:17
4

An operation queue example for your comparison:

- (void)viewDidLoad
{
  // ...

  self.queue = [[NSOperationQueue alloc] init];

  // ...
}

- (void)job
{
  // background activities ...
}

- (void)startJob
{
  NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self 
                                                                   selector:@selector(job) 
                                                                     object:nil];
  [self.queue addOperation:op];
}
ohho
  • 50,879
  • 75
  • 256
  • 383