Block Operation

BlockOperation is initialized with a block to execute. This is probably the most handy and versatile operation class, as it can be used to execute a block on a queue, just like dispatch_async but with the features of operations such as dependencies, observers and conditions.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let show = BlockOperation {
        self.navigationController?.pushViewController(viewController, animated: true)
    }
    
    show.addCondition(MutuallyExclusive<UIViewController>())
    
    show.addObserver(FinishedObserver { _, errors in
        dispatch_async(Queue.Main.queue) {
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
        }
    })
    
    queue.addOperation(show)
}

The example above uses a BlockOperation to push a view controller onto a navigation controller within a UITableViewDelegate callback. We can add a condition that prevents other UIViewController based operations from running, and an observer to deselect the row when it completes.

In this example, the BlockOperation is initialized with a dispatch_block_t which is executed on the main queue. This makes it ideal for UI based operations such as this. In addition the BlockOperation will automatically finish after the block exists. Therefore it can only be used for synchronous tasks.

To execute the block directly on the operation queue, we must use a different initializer.

let operation = BlockOperation { (continuation: BlockOperation.ContinuationBlockType) in
    doSomeWork()
    continuation(error: nil)
}

In the above example, the block receives a continuation block as an argument. This continuation block must be called to finish the operation. It accepts a ErrorType? which means that the block can finish with an error if needed.

🚧

Always execute the continuation block

If the continuation block is not called the queue can potentially become blocked. There is probably going to be some improvements in regard to this. Firstly making the closure easier to to write, and potentially automatically adding a TimeoutObserver to BlockOperation when in debug configuration.

When using BlockOperation on the queue with a continuation argument, it is also possible to start other asynchronous tasks which have completion handers. For these cases the continuation block can be executed inside the completion handler. This can be useful to bridge to other asynchronous systems.


Did this page help you?