{"__v":9,"_id":"5673fefdf65d9c0d002e3d52","category":{"__v":7,"_id":"567400638565060d009a86fb","pages":["567400df22cd7e0d00fada7f","56740103f65d9c0d002e3d5e","5674010f47f7010d005bff1a","56740128f79ca90d00ad2f65","5674014947f7010d005bff1c","5674015622cd7e0d00fada81","5674016058c4890d00bb5558"],"project":"5672fc989996590d00c22c65","version":"5672fc989996590d00c22c68","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-12-18T12:47:31.547Z","from_sync":false,"order":2,"slug":"available-operations","title":"Available Operations"},"project":"5672fc989996590d00c22c65","user":"5654ea8be0d82b0d00ab5747","version":{"__v":7,"_id":"5672fc989996590d00c22c68","project":"5672fc989996590d00c22c65","createdAt":"2015-12-17T18:19:04.699Z","releaseDate":"2015-12-17T18:19:04.699Z","categories":["5672fc999996590d00c22c69","567301169d4c060d009da8b3","56730183547bee0d00997d1a","5673018a06b19d0d0010691b","567301b53054630d00fe9288","567400638565060d009a86fb","5674017bf79ca90d00ad2f67"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.5.0","version":"2.5.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-12-18T12:41:33.040Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"`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.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {\\n\\n    let show = BlockOperation {\\n        self.navigationController?.pushViewController(viewController, animated: true)\\n    }\\n    \\n    show.addCondition(MutuallyExclusive<UIViewController>())\\n    \\n    show.addObserver(FinishedObserver { _, errors in\\n        dispatch_async(Queue.Main.queue) {\\n            tableView.deselectRowAtIndexPath(indexPath, animated: true)\\n        }\\n    })\\n    \\n    queue.addOperation(show)\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nThe 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.\n\nIn 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.\n\nTo execute the block directly on the operation queue, we must use a different initializer.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"let operation = BlockOperation { (continuation: BlockOperation.ContinuationBlockType) in\\n    doSomeWork()\\n    continuation(error: nil)\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nIn 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.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"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.\",\n  \"title\": \"Always execute the continuation block\"\n}\n[/block]\nWhen 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.","excerpt":"","slug":"block-operation","type":"basic","title":"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. [block:code] { "codes": [ { "code": "func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {\n\n let show = BlockOperation {\n self.navigationController?.pushViewController(viewController, animated: true)\n }\n \n show.addCondition(MutuallyExclusive<UIViewController>())\n \n show.addObserver(FinishedObserver { _, errors in\n dispatch_async(Queue.Main.queue) {\n tableView.deselectRowAtIndexPath(indexPath, animated: true)\n }\n })\n \n queue.addOperation(show)\n}", "language": "swift" } ] } [/block] 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. [block:code] { "codes": [ { "code": "let operation = BlockOperation { (continuation: BlockOperation.ContinuationBlockType) in\n doSomeWork()\n continuation(error: nil)\n}", "language": "swift" } ] } [/block] 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. [block:callout] { "type": "warning", "body": "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.", "title": "Always execute the continuation block" } [/block] 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.