SlideShare a Scribd company logo
1 of 45
Download to read offline
THREADS, QUEUES,
AND MORE: ASYNC
PROGRAMMING
IN IOS
Why Async?
Long running is:
>= 0.01666 seconds
Perform long running tasks
asynchronously
Threads vs Queues
QueueThread
QueueThreads
Main Queue
Main Queue
UI
{
code…
}
UI UI
{
code…
}
{
…
}
Main Queue manages the main thread
Main Queue
UI
{
code…
}
UI UI
{
code…
}
{
…
}
User Interface / UIKit all happens on the main queue
Main Queue
UI
{
code…
}
UI UI
{
code…
}
{
…
}
Any custom code in view controllers (for example, viewDidLoad)
executes on main queue
Main Queue
How do we get off
the main queue?
NSObject / NSThread
Grand Central Dispatch
NSOperation
Networking
NSObject / NSThread
NSObject methods
- performSelector:withObject:afterDelay:
- performSelector:withObject:afterDelay:inModes:
- performSelectorOnMainThread:withObject:waitUntilDone:
- performSelectorOnMainThread:withObject:waitUntilDone:modes:
- performSelector:onThread:withObject:waitUntilDone:
- performSelector:onThread:withObject:waitUntilDone:modes:
- performSelectorInBackground:withObject:
…this approach uses threads,
not queues.
NOT recommended.
Grand Central Dispatch
Grand Central Dispatch
• Dispatch Queues
• Global
• Concurrent
• Serial
• Dispatch Groups
Dispatch Queues
First, get a reference
to the queue
Dispatch Async - Swift 3
let queue = DispatchQueue.global(qos: .background)
for iteration in 1...iterations {
queue.async { [weak self] in
self?.longRunningTask(with: iteration)
}
}
Dispatch Queue Types - Swift 3
let queue:DispatchQueue
switch approach {
case .dispatchConcurrent:
queue = DispatchQueue.global(qos: .default)
case .dispatchSerial:
queue = DispatchQueue(label: "SerialQueue")
default:
queue = DispatchQueue(label: "ConcurrentQueue",
qos: .background,
attributes: .concurrent,
autoreleaseFrequency: .inherit,
target: nil)
}
Add work
to the queue
Dispatch Async - Swift 3
let queue = DispatchQueue.global(qos: .background)
for iteration in 1...iterations {
queue.async { [weak self] in
self?.longRunningTask(with: iteration)
}
}
Dispatch Work Item - Swift 3
let workItem = DispatchWorkItem(qos: .default,
flags: .assignCurrentContext) {
…
}
queue.async(execute: workItem)
Go back to the main queue
to update UI
Dispatch Async - Swift 3
…
DispatchQueue.main.async {
strongSelf.taskDelegate?.longRunningTaskDidComplete(with: results)
}
How does it look?
Group tasks
First, create a group
Dispatch Group - Swift 3
func performLongRunningTask(with iterations:Int) {
let queue:DispatchQueue = DispatchQueue.global(qos: .default)
let workGroup = DispatchGroup()
for iteration in 1...iterations {
print("In iteration (iteration)")
queue.async { [weak self] in
workGroup.enter()
self?.longRunningTask(with: iteration)
workGroup.leave()
}
}
workGroup.notify(queue: queue) {
DispatchQueue.main.async {
self.taskDelegate?.longRunningTaskDidComplete(with: self.results)
print("Called delegate for group")
}
}
}
Enter the group
Dispatch Group - Swift 3
func performLongRunningTask(with iterations:Int) {
let queue:DispatchQueue = DispatchQueue.global(qos: .default)
let workGroup = DispatchGroup()
for iteration in 1...iterations {
print("In iteration (iteration)")
queue.async { [weak self] in
workGroup.enter()
self?.longRunningTask(with: iteration)
workGroup.leave()
}
}
workGroup.notify(queue: queue) {
DispatchQueue.main.async {
self.taskDelegate?.longRunningTaskDidComplete(with: self.results)
print("Called delegate for group")
}
}
}
Do your work
Dispatch Group - Swift 3
func longRunningTask(with iteration:Int) {
var iterationResults:[String] = []
for counter in 1...10 {
Thread.sleep(forTimeInterval: 0.1)
iterationResults.append("Iteration (iteration) - Item (counter)")
}
if self.approach == .dispatchGroup {
self.results.append(contentsOf: iterationResults)
} else {
self.resultsQueue.sync {
self.results.append(contentsOf: iterationResults)
}
}
}
Leave the group
Dispatch Group - Swift 3
func performLongRunningTask(with iterations:Int) {
let queue:DispatchQueue = DispatchQueue.global(qos: .default)
let workGroup = DispatchGroup()
for iteration in 1...iterations {
print("In iteration (iteration)")
queue.async { [weak self] in
workGroup.enter()
self?.longRunningTask(with: iteration)
workGroup.leave()
}
}
workGroup.notify(queue: queue) {
DispatchQueue.main.async {
self.taskDelegate?.longRunningTaskDidComplete(with: self.results)
print("Called delegate for group")
}
}
}
Notify - group is “done”
Dispatch Group - Swift 3
func performLongRunningTask(with iterations:Int) {
let queue:DispatchQueue = DispatchQueue.global(qos: .default)
let workGroup = DispatchGroup()
for iteration in 1...iterations {
print("In iteration (iteration)")
queue.async { [weak self] in
workGroup.enter()
self?.longRunningTask(with: iteration)
workGroup.leave()
}
}
workGroup.notify(queue: queue) {
DispatchQueue.main.async {
self.taskDelegate?.longRunningTaskDidComplete(with: self.results)
print("Called delegate for group")
}
}
}
How does it look?
Broken! What’s wrong?
Arrays are *not*
thread safe
Try with sync approach
Dispatch Group - Swift 3
func longRunningTask(with iteration:Int) {
var iterationResults:[String] = []
for counter in 1...10 {
Thread.sleep(forTimeInterval: 0.1)
iterationResults.append("Iteration (iteration) - Item (counter)")
}
if self.approach == .dispatchGroup {
self.results.append(contentsOf: iterationResults)
} else {
self.resultsQueue.sync {
self.results.append(contentsOf: iterationResults)
}
}
}
Better?
OperationQueue
Create an OperationQueue
OperationQueue - Swift 3
var taskOperationQueue:OperationQueue = OperationQueue()
// for a serial queue, do this:
taskOperationQueue.maxConcurrentOperationCount = 1
Add an Operation
to the Queue
OperationQueue - Swift 3
for iteration in 1...iterations {
taskOperationQueue.addOperation({ [weak self] in
self?.longRunningTask(with: iteration)
})
}
OperationQueue - Swift 3
var operationsToAdd:[Operation] = []
var previousOperation:Operation?
for iteration in 1...iterations {
let newOperation = CustomOperation(iteration: iteration,
delegate: taskDelegate)
if let actualPreviousOperation = previousOperation {
newOperation.addDependency(actualPreviousOperation)
}
operationsToAdd.append(newOperation)
previousOperation = newOperation
}
taskOperationQueue.addOperations(operationsToAdd, waitUntilFinished: false)
Go back to the main queue
to update UI
OperationQueue - Swift 3
OperationQueue.main.addOperation {
strongSelf.taskDelegate?.longRunningTaskDidComplete(with: results)
}
In action…
OperationQueue
• InvocationOperation, BlockOperation, or Operation subclass
• OperationQueues and Operations support cancellation
• OperationQueues and Operations support dependencies, even across queues
• Can suspend and resume a queue; clear all operations out of a queue
Networking
Use URLSession &
URLSessionTasks
Networking - Swift 3
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 5
config.httpAdditionalHeaders =
["X-Token":"F06427CB-00AE-422C-992F-854689B5419E"]
self.urlSession = URLSession(configuration: config)
Networking - Swift 3
var iterationComponents:URLComponents = URLComponents()
iterationComponents.scheme = "http"
iterationComponents.host = "joes-macbook-air.local"
iterationComponents.port = 8080
iterationComponents.path = "/iteration(iteration).json"
guard let iterationURL = iterationComponents.url else {
return nil
}
let request = URLRequest(url: iterationURL)
let task = urlSession?.dataTask(with: request, completionHandler:
{ (data, response, error) in
…
}
NOTE: “error” means cannot
connect to host
Response may also be an error.
Check response status code too.
Networking - Swift 3
if let actualError = error {
print("Error encountered with data task: (actualError.localizedDescription)")
return
}
guard let actualResponse = response as? HTTPURLResponse,
actualResponse.statusCode == 200 else {
print("Unexpected response received")
return
}
Completion handler is on
background queue -
do your “heavy lifting” there
Networking - Swift 3
guard let actualData = data else {
print("No data received...")
return
}
let json = try? JSONSerialization.jsonObject(with: actualData,
options: [])
guard let info = json as? [String:Any],
let results = info["iterations"] as? [String] else {
print("Data received was not in the expected format")
return
}
Dispatch to main queue to
update UI with results
Networking - Swift 3
DispatchQueue.main.async {
self.taskDelegate?.longRunningTaskDidComplete(with: results)
}
Things to Avoid
General Async Risks
Simultaneous Updates
Race Conditions /
Out of Sequence Updates
Deadlocks
Thread Explosion
Updating UI from
background thread
Unexpected queue from
block-based SDK method
Unexpected Queue
In iOS SDK, watch out for:
• Completion Handlers
• Error Handlers
• any method parameter titled “withBlock:”
Over-dispatching
Over-dispatching
dispatch_queue_t workQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(workQueue, ^{
[[self managedObjectContext] performBlock:^{
[testObject setValue:@"test" forKey:@"testKey"];
}];
});
Retain Cycles
Retain Cycles
• Happens when the caller retains the block or closure, and the block or closure retains the
caller.
• Different semantics for preventing in Objective-C, Swift 3.0
• Gist is: Avoid a strong reference to the caller from the block / closure unless absolutely
necessary, and make sure the reference gets released
Learn more?
MARTIANCRAFT TRAINING…
@jwkeeley
THANK YOU
martiancraft.com

More Related Content

What's hot

Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
New Relic
 
Concurrency Utilities in Java 8
Concurrency Utilities in Java 8Concurrency Utilities in Java 8
Concurrency Utilities in Java 8
Martin Toshev
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
Luca Mearelli
 

What's hot (20)

Djangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New RelicDjangocon11: Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
 
Building Distributed System with Celery on Docker Swarm
Building Distributed System with Celery on Docker SwarmBuilding Distributed System with Celery on Docker Swarm
Building Distributed System with Celery on Docker Swarm
 
Scaling up task processing with Celery
Scaling up task processing with CeleryScaling up task processing with Celery
Scaling up task processing with Celery
 
Building Distributed System with Celery on Docker Swarm - PyCon JP 2016
Building Distributed System with Celery on Docker Swarm - PyCon JP 2016Building Distributed System with Celery on Docker Swarm - PyCon JP 2016
Building Distributed System with Celery on Docker Swarm - PyCon JP 2016
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
 
Node.js behind: V8 and its optimizations
Node.js behind: V8 and its optimizationsNode.js behind: V8 and its optimizations
Node.js behind: V8 and its optimizations
 
Celery
CeleryCelery
Celery
 
Concurrent Programming in Java
Concurrent Programming in JavaConcurrent Programming in Java
Concurrent Programming in Java
 
Entity Component System - for App developers
Entity Component System - for App developersEntity Component System - for App developers
Entity Component System - for App developers
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
 
Concurrency Utilities in Java 8
Concurrency Utilities in Java 8Concurrency Utilities in Java 8
Concurrency Utilities in Java 8
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
Python在豆瓣的应用
Python在豆瓣的应用Python在豆瓣的应用
Python在豆瓣的应用
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
Python, do you even async?
Python, do you even async?Python, do you even async?
Python, do you even async?
 
JavaExamples
JavaExamplesJavaExamples
JavaExamples
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetup
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 

Similar to Threads, Queues, and More: Async Programming in iOS

Advanced iOS Build Mechanics, Sebastien Pouliot
Advanced iOS Build Mechanics, Sebastien PouliotAdvanced iOS Build Mechanics, Sebastien Pouliot
Advanced iOS Build Mechanics, Sebastien Pouliot
Xamarin
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
Ben Lin
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and views
priestc
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 

Similar to Threads, Queues, and More: Async Programming in iOS (20)

Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Celery
CeleryCelery
Celery
 
[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
 
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
 
Celery with python
Celery with pythonCelery with python
Celery with python
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
 
Parallel Processing
Parallel ProcessingParallel Processing
Parallel Processing
 
Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#Workshop: Async and Parallel in C#
Workshop: Async and Parallel in C#
 
Advanced iOS Build Mechanics, Sebastien Pouliot
Advanced iOS Build Mechanics, Sebastien PouliotAdvanced iOS Build Mechanics, Sebastien Pouliot
Advanced iOS Build Mechanics, Sebastien Pouliot
 
How to instantiate any view controller for free
How to instantiate any view controller for freeHow to instantiate any view controller for free
How to instantiate any view controller for free
 
Future Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NETFuture Decoded - Node.js per sviluppatori .NET
Future Decoded - Node.js per sviluppatori .NET
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customization
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Appium Automation with Kotlin
Appium Automation with KotlinAppium Automation with Kotlin
Appium Automation with Kotlin
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Models, controllers and views
Models, controllers and viewsModels, controllers and views
Models, controllers and views
 
C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴C#을 이용한 task 병렬화와 비동기 패턴
C#을 이용한 task 병렬화와 비동기 패턴
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 

More from TechWell

More from TechWell (20)

Failing and Recovering
Failing and RecoveringFailing and Recovering
Failing and Recovering
 
Instill a DevOps Testing Culture in Your Team and Organization
Instill a DevOps Testing Culture in Your Team and Organization Instill a DevOps Testing Culture in Your Team and Organization
Instill a DevOps Testing Culture in Your Team and Organization
 
Test Design for Fully Automated Build Architecture
Test Design for Fully Automated Build ArchitectureTest Design for Fully Automated Build Architecture
Test Design for Fully Automated Build Architecture
 
System-Level Test Automation: Ensuring a Good Start
System-Level Test Automation: Ensuring a Good StartSystem-Level Test Automation: Ensuring a Good Start
System-Level Test Automation: Ensuring a Good Start
 
Build Your Mobile App Quality and Test Strategy
Build Your Mobile App Quality and Test StrategyBuild Your Mobile App Quality and Test Strategy
Build Your Mobile App Quality and Test Strategy
 
Testing Transformation: The Art and Science for Success
Testing Transformation: The Art and Science for SuccessTesting Transformation: The Art and Science for Success
Testing Transformation: The Art and Science for Success
 
Implement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlowImplement BDD with Cucumber and SpecFlow
Implement BDD with Cucumber and SpecFlow
 
Develop WebDriver Automated Tests—and Keep Your Sanity
Develop WebDriver Automated Tests—and Keep Your SanityDevelop WebDriver Automated Tests—and Keep Your Sanity
Develop WebDriver Automated Tests—and Keep Your Sanity
 
Ma 15
Ma 15Ma 15
Ma 15
 
Eliminate Cloud Waste with a Holistic DevOps Strategy
Eliminate Cloud Waste with a Holistic DevOps StrategyEliminate Cloud Waste with a Holistic DevOps Strategy
Eliminate Cloud Waste with a Holistic DevOps Strategy
 
Transform Test Organizations for the New World of DevOps
Transform Test Organizations for the New World of DevOpsTransform Test Organizations for the New World of DevOps
Transform Test Organizations for the New World of DevOps
 
The Fourth Constraint in Project Delivery—Leadership
The Fourth Constraint in Project Delivery—LeadershipThe Fourth Constraint in Project Delivery—Leadership
The Fourth Constraint in Project Delivery—Leadership
 
Resolve the Contradiction of Specialists within Agile Teams
Resolve the Contradiction of Specialists within Agile TeamsResolve the Contradiction of Specialists within Agile Teams
Resolve the Contradiction of Specialists within Agile Teams
 
Pin the Tail on the Metric: A Field-Tested Agile Game
Pin the Tail on the Metric: A Field-Tested Agile GamePin the Tail on the Metric: A Field-Tested Agile Game
Pin the Tail on the Metric: A Field-Tested Agile Game
 
Agile Performance Holarchy (APH)—A Model for Scaling Agile Teams
Agile Performance Holarchy (APH)—A Model for Scaling Agile TeamsAgile Performance Holarchy (APH)—A Model for Scaling Agile Teams
Agile Performance Holarchy (APH)—A Model for Scaling Agile Teams
 
A Business-First Approach to DevOps Implementation
A Business-First Approach to DevOps ImplementationA Business-First Approach to DevOps Implementation
A Business-First Approach to DevOps Implementation
 
Databases in a Continuous Integration/Delivery Process
Databases in a Continuous Integration/Delivery ProcessDatabases in a Continuous Integration/Delivery Process
Databases in a Continuous Integration/Delivery Process
 
Mobile Testing: What—and What Not—to Automate
Mobile Testing: What—and What Not—to AutomateMobile Testing: What—and What Not—to Automate
Mobile Testing: What—and What Not—to Automate
 
Cultural Intelligence: A Key Skill for Success
Cultural Intelligence: A Key Skill for SuccessCultural Intelligence: A Key Skill for Success
Cultural Intelligence: A Key Skill for Success
 
Turn the Lights On: A Power Utility Company's Agile Transformation
Turn the Lights On: A Power Utility Company's Agile TransformationTurn the Lights On: A Power Utility Company's Agile Transformation
Turn the Lights On: A Power Utility Company's Agile Transformation
 

Recently uploaded

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 

Recently uploaded (20)

Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban%in Durban+277-882-255-28 abortion pills for sale in Durban
%in Durban+277-882-255-28 abortion pills for sale in Durban
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 

Threads, Queues, and More: Async Programming in iOS

  • 1. THREADS, QUEUES, AND MORE: ASYNC PROGRAMMING IN IOS Why Async?
  • 2. Long running is: >= 0.01666 seconds
  • 3. Perform long running tasks asynchronously Threads vs Queues
  • 5. Main Queue Main Queue UI { code… } UI UI { code… } { … } Main Queue manages the main thread
  • 6. Main Queue UI { code… } UI UI { code… } { … } User Interface / UIKit all happens on the main queue Main Queue UI { code… } UI UI { code… } { … } Any custom code in view controllers (for example, viewDidLoad) executes on main queue
  • 7. Main Queue How do we get off the main queue?
  • 8. NSObject / NSThread Grand Central Dispatch NSOperation Networking NSObject / NSThread
  • 9. NSObject methods - performSelector:withObject:afterDelay: - performSelector:withObject:afterDelay:inModes: - performSelectorOnMainThread:withObject:waitUntilDone: - performSelectorOnMainThread:withObject:waitUntilDone:modes: - performSelector:onThread:withObject:waitUntilDone: - performSelector:onThread:withObject:waitUntilDone:modes: - performSelectorInBackground:withObject: …this approach uses threads, not queues. NOT recommended.
  • 10. Grand Central Dispatch Grand Central Dispatch • Dispatch Queues • Global • Concurrent • Serial • Dispatch Groups
  • 11. Dispatch Queues First, get a reference to the queue
  • 12. Dispatch Async - Swift 3 let queue = DispatchQueue.global(qos: .background) for iteration in 1...iterations { queue.async { [weak self] in self?.longRunningTask(with: iteration) } } Dispatch Queue Types - Swift 3 let queue:DispatchQueue switch approach { case .dispatchConcurrent: queue = DispatchQueue.global(qos: .default) case .dispatchSerial: queue = DispatchQueue(label: "SerialQueue") default: queue = DispatchQueue(label: "ConcurrentQueue", qos: .background, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil) }
  • 13. Add work to the queue Dispatch Async - Swift 3 let queue = DispatchQueue.global(qos: .background) for iteration in 1...iterations { queue.async { [weak self] in self?.longRunningTask(with: iteration) } }
  • 14. Dispatch Work Item - Swift 3 let workItem = DispatchWorkItem(qos: .default, flags: .assignCurrentContext) { … } queue.async(execute: workItem) Go back to the main queue to update UI
  • 15. Dispatch Async - Swift 3 … DispatchQueue.main.async { strongSelf.taskDelegate?.longRunningTaskDidComplete(with: results) } How does it look?
  • 16.
  • 18. Dispatch Group - Swift 3 func performLongRunningTask(with iterations:Int) { let queue:DispatchQueue = DispatchQueue.global(qos: .default) let workGroup = DispatchGroup() for iteration in 1...iterations { print("In iteration (iteration)") queue.async { [weak self] in workGroup.enter() self?.longRunningTask(with: iteration) workGroup.leave() } } workGroup.notify(queue: queue) { DispatchQueue.main.async { self.taskDelegate?.longRunningTaskDidComplete(with: self.results) print("Called delegate for group") } } } Enter the group
  • 19. Dispatch Group - Swift 3 func performLongRunningTask(with iterations:Int) { let queue:DispatchQueue = DispatchQueue.global(qos: .default) let workGroup = DispatchGroup() for iteration in 1...iterations { print("In iteration (iteration)") queue.async { [weak self] in workGroup.enter() self?.longRunningTask(with: iteration) workGroup.leave() } } workGroup.notify(queue: queue) { DispatchQueue.main.async { self.taskDelegate?.longRunningTaskDidComplete(with: self.results) print("Called delegate for group") } } } Do your work
  • 20. Dispatch Group - Swift 3 func longRunningTask(with iteration:Int) { var iterationResults:[String] = [] for counter in 1...10 { Thread.sleep(forTimeInterval: 0.1) iterationResults.append("Iteration (iteration) - Item (counter)") } if self.approach == .dispatchGroup { self.results.append(contentsOf: iterationResults) } else { self.resultsQueue.sync { self.results.append(contentsOf: iterationResults) } } } Leave the group
  • 21. Dispatch Group - Swift 3 func performLongRunningTask(with iterations:Int) { let queue:DispatchQueue = DispatchQueue.global(qos: .default) let workGroup = DispatchGroup() for iteration in 1...iterations { print("In iteration (iteration)") queue.async { [weak self] in workGroup.enter() self?.longRunningTask(with: iteration) workGroup.leave() } } workGroup.notify(queue: queue) { DispatchQueue.main.async { self.taskDelegate?.longRunningTaskDidComplete(with: self.results) print("Called delegate for group") } } } Notify - group is “done”
  • 22. Dispatch Group - Swift 3 func performLongRunningTask(with iterations:Int) { let queue:DispatchQueue = DispatchQueue.global(qos: .default) let workGroup = DispatchGroup() for iteration in 1...iterations { print("In iteration (iteration)") queue.async { [weak self] in workGroup.enter() self?.longRunningTask(with: iteration) workGroup.leave() } } workGroup.notify(queue: queue) { DispatchQueue.main.async { self.taskDelegate?.longRunningTaskDidComplete(with: self.results) print("Called delegate for group") } } } How does it look?
  • 24. Arrays are *not* thread safe Try with sync approach
  • 25. Dispatch Group - Swift 3 func longRunningTask(with iteration:Int) { var iterationResults:[String] = [] for counter in 1...10 { Thread.sleep(forTimeInterval: 0.1) iterationResults.append("Iteration (iteration) - Item (counter)") } if self.approach == .dispatchGroup { self.results.append(contentsOf: iterationResults) } else { self.resultsQueue.sync { self.results.append(contentsOf: iterationResults) } } } Better?
  • 27. Create an OperationQueue OperationQueue - Swift 3 var taskOperationQueue:OperationQueue = OperationQueue() // for a serial queue, do this: taskOperationQueue.maxConcurrentOperationCount = 1
  • 28. Add an Operation to the Queue OperationQueue - Swift 3 for iteration in 1...iterations { taskOperationQueue.addOperation({ [weak self] in self?.longRunningTask(with: iteration) }) }
  • 29. OperationQueue - Swift 3 var operationsToAdd:[Operation] = [] var previousOperation:Operation? for iteration in 1...iterations { let newOperation = CustomOperation(iteration: iteration, delegate: taskDelegate) if let actualPreviousOperation = previousOperation { newOperation.addDependency(actualPreviousOperation) } operationsToAdd.append(newOperation) previousOperation = newOperation } taskOperationQueue.addOperations(operationsToAdd, waitUntilFinished: false) Go back to the main queue to update UI
  • 30. OperationQueue - Swift 3 OperationQueue.main.addOperation { strongSelf.taskDelegate?.longRunningTaskDidComplete(with: results) } In action…
  • 31.
  • 32. OperationQueue • InvocationOperation, BlockOperation, or Operation subclass • OperationQueues and Operations support cancellation • OperationQueues and Operations support dependencies, even across queues • Can suspend and resume a queue; clear all operations out of a queue Networking
  • 33. Use URLSession & URLSessionTasks Networking - Swift 3 let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 5 config.httpAdditionalHeaders = ["X-Token":"F06427CB-00AE-422C-992F-854689B5419E"] self.urlSession = URLSession(configuration: config)
  • 34. Networking - Swift 3 var iterationComponents:URLComponents = URLComponents() iterationComponents.scheme = "http" iterationComponents.host = "joes-macbook-air.local" iterationComponents.port = 8080 iterationComponents.path = "/iteration(iteration).json" guard let iterationURL = iterationComponents.url else { return nil } let request = URLRequest(url: iterationURL) let task = urlSession?.dataTask(with: request, completionHandler: { (data, response, error) in … } NOTE: “error” means cannot connect to host Response may also be an error. Check response status code too.
  • 35. Networking - Swift 3 if let actualError = error { print("Error encountered with data task: (actualError.localizedDescription)") return } guard let actualResponse = response as? HTTPURLResponse, actualResponse.statusCode == 200 else { print("Unexpected response received") return } Completion handler is on background queue - do your “heavy lifting” there
  • 36. Networking - Swift 3 guard let actualData = data else { print("No data received...") return } let json = try? JSONSerialization.jsonObject(with: actualData, options: []) guard let info = json as? [String:Any], let results = info["iterations"] as? [String] else { print("Data received was not in the expected format") return } Dispatch to main queue to update UI with results
  • 37. Networking - Swift 3 DispatchQueue.main.async { self.taskDelegate?.longRunningTaskDidComplete(with: results) } Things to Avoid
  • 39. Race Conditions / Out of Sequence Updates Deadlocks
  • 40. Thread Explosion Updating UI from background thread
  • 42. Unexpected Queue In iOS SDK, watch out for: • Completion Handlers • Error Handlers • any method parameter titled “withBlock:” Over-dispatching
  • 43. Over-dispatching dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); dispatch_async(workQueue, ^{ [[self managedObjectContext] performBlock:^{ [testObject setValue:@"test" forKey:@"testKey"]; }]; }); Retain Cycles
  • 44. Retain Cycles • Happens when the caller retains the block or closure, and the block or closure retains the caller. • Different semantics for preventing in Objective-C, Swift 3.0 • Gist is: Avoid a strong reference to the caller from the block / closure unless absolutely necessary, and make sure the reference gets released Learn more? MARTIANCRAFT TRAINING…