WWDC App
- Download Settings
- Download Schedule
- Download News
- Download Video list
- Mark Favorites
- Leave Feedback
- Log In
- Developer Status
- Download Pass
- Download Photos
- Watch Videos
- Push Notifications
- Access CloudKit
- Location Permission
- Display Alerts Upload
- Analytics
Agenda
- Core Concepts
- Beyond the Basics
- Sample Code
Core Concepts
- High-level dispatch_queue_t
- Cancellation
- maxConcurrentOperationCount
Serial Queues
maxConcurrentOperationCount = 1Concurrent Queues
maxConcurrentOperationCount = DefaultNSOperation
- High-level dispatch_block_t
- Long-running task
- Subclassable
Lifecycle of an NSOperation

Cancellation
var cancelled: Bool { get }- Only changes state
- Subclasses dictate meaning
- Susceptible to race conditions
operationA.cancel()Readiness
var ready: Bool { get }Execute when ready
Serial Operation Queues
- Readiness
Dependencies
- “First this, then that”
- Strict ordering
- Implemented via readiness
- Not limited by queues
let operationA = ...
let operationB = ...
operationB.addDependency(operationA)- Operation deadlock
WWDC App Favorites

WWDC App Startup

Abstraction
- Operations abstract logic
- Simplifies logic changes
- WWDC app
    - Custom backend CloudKit
 
- Grand Central Dispatch?
Beyond the Basics
UI Operations
Not just the background
- Authentication Videos
- Alerts
- “Modal” UI
Block Operations

It’s blocks all the way down
- NSOperation to execute a block
- Dependencies for blocks
- Leaving feedback
WWDC App
- Block operations
Generating Dependencies
When two operations love each other…
- “Never execute this until after executing that”
- Saving a favorite
- Downloading pass
- Anything requiring login
WWDC app favorites

Extending Readiness
Adding requirements
- “Only execute this if…”
- 
    Examples - Network is reachable
- Access to user location
- User is “logged in”
 
Composing Operations
Downloading and parsing

I heard you like operations…
- Downloading and parsing
- Fetching favorites
WWDC App
Fetching favorites
override public func execute() {
	let userRecordID: CKRecordID = ...
	let predicate = NSPredicate(format: "creatorUserRecordID = %@", userRecordID)
	let query = CKQuery(recordType: "SessionFavorite", predicate: predicate)
	let queryOperation = CKQueryOperation(query)
	executeQueryOperation(queryOperation)
}
private func executeQueryOperation(queryOperation: CKQueryOperation) {
	queryOperation.recordFetchedBlock = ...
	queryOperation.queryCompletionBlock = { cursor, error in
		if let error = error {
			self.finishWithError(error)
		} else if let cursor = cursor {
			let fetchMoreRecords = CKQueryOperation(cursor)
				self.executeQueryOperation(fetchMoreRecords)
		} else {
			self.processFetchedRecords()
		}
	}
	database.addOperation(queryOperation)
}Mutual Exclusivity
There can be only one
- Alerts
- Videos
- Loading database
One alert at a time

Sample Code
- Earthquakes and Operations <developer.apple.com/wwdc>
Operation
- NSOperation subclass
- Adds “conditions”
- Adds “observers”
- 
    Example operations - Groups
- URLSessionTask
- Location
- Delay
 
OperationCondition
- Generates dependencies
- Defines mutual exclusivity
- Checks for satisfied conditions
- Example conditions
    - MutuallyExclusive
- Reachability
- Permissions
 
- MutuallyExclusive
OperationObserver
- Notified about significant events
    - Operation start
- Operation end
- Operation generation
 
- Example observers
    - Timeouts
- Background tasks
- Network activity indicator
 
Summary
- Operations abstract logic
- Dependencies clarify intent
- Describe complex behaviors
- Enables powerful patterns
Related Sessions
- Building Responsive and Efficient Apps with GCD CloudKit Tips and Tricks
- Advanced CloudKit
- Nob Hill Pacific Heights (WWDC14)