itp 342 mobile app dev - university of southern...

30
ITP 342 Mobile App Dev Grand Central Dispatch Background Processing

Upload: lamnguyet

Post on 09-Sep-2018

217 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

ITP 342 Mobile App Dev

Grand Central Dispatch

Background Processing

Page 2: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Grand Central Dispatch (GCD) •  New API for splitting up the work your app

needs to do into smaller chunks that can be spread across multiple thread and, with the right hardware, multiple CPUs

•  Much of the new API is accessed using blocks –  In-line function capability to C & Objective-C

2

Page 3: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Threading Basics •  Most modern operating systems support the notion of

threads of execution •  Each process can contain multiple threads which all

run concurrently –  If there's just one processor core, the operating system

will switch between all executing threads –  If more than one core is available, the threads will be

distributed among them •  All threads in a process share the same executable

program code and the same global data •  Each thread can also have some data that is

exclusive to the thread

3

Page 4: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Threading Basics •  Mutex (mutual exclusion) or lock

–  Special structure that threads can make use of –  Ensures that a particular chunk of code can't be

run by multiple threads at once –  Use in a critical section of your code –  This makes them thread-safe

4

Page 5: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Thread-Safe •  In Cocoa Touch, the Foundation framework

(NSString, NSArray, etc.) is thread-safe –  The UIKit framework is for the most part not thread-

safe •  Main thread is where all the action of your iOS

app occurs –  All method calls that deal with any UIKit object should

be executed in the main thread •  https://developer.apple.com/library/ios/

documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html

5

Page 6: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Units of Work •  It is possible to implement some concurrency

without too much low-level thread-twisting •  Split up long-running tasks into units of work

and put those units into queues for execution •  The system manages the queues for us,

executing units of work on multiple threads

6

Page 7: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

GCD: Low-Level Queueing •  GCD made its debut in Mac OS X 10.6 •  Available since iOS 4.0 •  Works with Objective-C, C, and C++ •  Key concepts is the queue •  The system provides a number of predefined

queues including one that does work on the main thread –  You can also create your own queues –  FIFO queues = first-in, first-out

7

Page 8: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Queueing •  Units of work added to a GCD queue will always

be started in the order they were placed in the queue –  They may not always finish in the same order due to

distributing its work among multiple threads •  Each queue has access to a pool of threads that

are reused throughout the lifetime of the app •  GCD will try to maintain a pool of threads

dependent on the machine's architecture •  Dual-core processors starting with iPad2 and

iPhone 4S –  Earlier devices are single-core

8

Page 9: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Blocks •  Blocks: known as closures or lambdas in other

languages •  Let a particular chunk of code be treated like any

other C-language type •  A block can be assigned to a variable, passed as an

argument to a function or method, and executed •  A block can take one or more parameters and specify

a return value –  To declare a block variable, use the caret (^) symbol

along with some additional parenthesized bits to declare parameters and return types

–  To define the block itself, you do roughly the same, but follow it up with the actual code defining the block wrapped in curly braces

9

Page 10: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Blocks - Example

10

// Declare a block variable "loggerBlock" with no parameters !// and no return value. !void (^loggerBlock)(void); !!// Assign a block to the variable declared above. !// A block without parameters and with no return value needs no !// "decorations" like the use of void in the variable declaration. !loggerBlock = ^{ ! NSLog(@"I'm just glad they didn't call it a lambda"); !}; !!// Execute the block, just like calling a function. !loggerBlock(); // this produces some output in the console !

Page 11: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Defining Blocks •  Similar to the concept of a function pointer in C,

but a few critical differences •  Blocks can be defined in-line in your code

–  Right at the point where it's going to be passed to another method or function

•  A block can access variables available in the scope where it's created –  By default, the block makes a copy of any variable

you access this way –  You can make an outside variable "read/write" by

prepending the storage qualifier __block before its declaration (that's 2 underscores)

11

Page 12: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Blocks - Example

12

// define a variable that cannot be changed by a block !int a = 0; !!// define a block that tries to modify a variable in its scope !void (^sillyBlock)(void) = ^{ a = 47; }; !!// check the value of our variable before calling the block !NSLog(@"a == %d", a); // outputs "a == 0" !!// execute the block !sillyBlock(); !!// check the values of our variable again, after calling the block !NSLog(@"a == %d", a); // outputs "a == 0" !

Page 13: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Blocks - Example

13

// define a variable that can be changed by a block !__block int a = 0; !!// define a block that tries to modify a variable in its scope !void (^sillyBlock)(void) = ^{ a = 47; }; !!// check the value of our variable before calling the block !NSLog(@"a == %d", a); // outputs "a == 0" !!// execute the block !sillyBlock(); !!// check the values of our variable again, after calling the block !NSLog(@"a == %d", a); // outputs "a == 47" !

Page 14: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

dispatch_async •  Make code run entirely in the background by

wrapping all the code in a block and passing it to a GCD function called dispatch_async!–  First parameter is a GCD queue

•  Using dispatch_get_global_queue() function –  DISPATCH_QUEUE_PRIORITY_HIGH !–  DISPATCH_QUEUE_PRIORITY_LOW !

–  Second parameter is a block to assign to the queue

14

dispatch_async (dispatch_get_global_queue ! (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ! // code !}); !

Page 15: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

The Main Thread •  One problem is UIKit thread-safety

–  Can't message any GUI object from a background thread

•  Solution is to pass the work to the main thread •  Call dispatch_async() with the first

parameter of dispatch_get_main_queue() !

15

dispatch_async (dispatch_get_main_queue(), ^{ ! // code !}); !

Page 16: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Concurrent Blocks •  Let's do things concurrently •  Use a dispatch group •  All blocks that are dispatched asynchronously

within the context of a group, via the dispatch_group_async() function, are set loose to execute as fast as they can –  Including being distributed to multiple threads for

concurrent execution, if possible •  Use dispatch_group_notify() to specify

an additional block that will be executed when all the blocks in the group have been run to completion

16

Page 17: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Worker •  Create a single-view app •  To the storyboard, add

–  Button (round rect button) –  Text View –  Activity Indicator View

•  In the Attributes Inspector, make sure Hides When Stopped is checked

•  Create IBOutlets –  Button à startButton –  TextView à resultsTextView

•  Create IBAction –  Button à doWork

17

Page 18: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Worker •  Add methods in implementation

18

- (NSString *) fetchSomethingFromServer { ! [NSThread sleepForTimeInterval:1]; ! return @"Fetched from Server"; !} !!- (NSString *) processData: (NSString *)data { ! [NSThread sleepForTimeInterval:2]; ! return [data uppercaseString]; !} !!- (NSString *) calculateFirstResult: (NSString *)data { ! [NSThread sleepForTimeInterval:3]; ! return [NSString stringWithFormat:@"Number of chars: %d", [data length]]; !} !!- (NSString *) calculateSecondResult: (NSString *)data { ! [NSThread sleepForTimeInterval:4]; ! return [data stringByReplacingOccurrencesOfString:@"E" withString:@"e"]; !} !

Page 19: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Slow Worker •  Implement doWork: method

19

- (IBAction) doWork: (id)sender { ! NSDate *startTime = [NSDate date]; ! ! NSString *fetchedData = [self fetchSomethingFromServer]; ! NSString *processedData = [self processData:fetchedData]; ! ! NSString *firstResult = [self calculateFirstResult:processedData]; ! NSString *secondResult = [self calculateSecondResult:processedData]; ! ! NSString *resultsSummary = [NSString stringWithFormat: ! @"First: [%@]\nSecond: [%@]", firstResult, secondResult]; !! self.resultsTextView.text = resultsSummary; ! ! NSDate *endTime = [NSDate date]; ! NSLog(@"Completed in %f seconds", ! [endTime timeIntervalSinceDate:startTime]); !} !

Page 20: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Faster Worker

20

- (IBAction)doWork:(id)sender { ! NSDate *startTime = [NSDate date]; !! // Disable the startButton! self.startButton.enabled = NO; ! self.startButton.alpha = 0.5f; ! ! // Start animating the spinner ! [self.spinner startAnimating]; ! ! // Grand Central Dispatch ! dispatch_queue_t queue = ! dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); ! dispatch_async(queue, ^{ !! NSString *fetchedData = [self fetchSomethingFromServer]; !! NSString *processedData = [self processData:fetchedData]; !!

Page 21: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Faster Worker

21

__block NSString *firstResult; ! __block NSString *secondResult; ! dispatch_group_t group = dispatch_group_create(); ! dispatch_group_async(group, queue, ^{ ! firstResult = [self calculateFirstResult:processedData]; ! }); ! dispatch_group_async(group, queue, ^{ ! secondResult = [self calculateSecondResult:processedData]; ! }); ! dispatch_group_notify(group, queue, ^{ ! NSString *resultsSummary = [NSString stringWithFormat: ! @"First: [%@]\nSecond: [%@]", firstResult, secondResult]; ! ! // Have to be on the main thread for UIKit objects ! dispatch_async(dispatch_get_main_queue(), ^{ ! self.resultsTextView.text = resultsSummary; ! self.startButton.enabled = YES; ! self.startButton.alpha = 1; ! [self.spinner stopAnimating]; ! }); ! NSDate *endTime = [NSDate date]; ! NSLog(@"Completed in %f seconds", ! [endTime timeIntervalSinceDate:startTime]); ! }); ! }); !} !

Page 22: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Background Processing •  Allows your apps to run in the background

–  Allows apps that require specific kinds of system functionality to continue to run in a constrained manner

•  Since iOS 4, iPhone 3GS & on, all iPads •  For example, an app that plays an audio stream

from an Internet radio station even if the user switches to another app

22

Page 23: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Application Life Cycle •  Not Running

–  This is the state that all apps are in on a freshly rebooted device

–  An app that has launched will return to this state only: •  In Info.plist, UIApplicatonExitsOnSuspend is set to YES •  It was previously Suspended and the system needs to

clear out some memory •  It crashes while running

23

Page 24: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Application Life Cycle •  Active

–  The normal running state of an app when it's displayed on the screen

–  Can receive user input & update the display •  Background

–  An app is given some time to execute some code but can't directly access the screen or get any user input

–  All apps enter this state when the user presses the home button •  Most of them quickly move on to Suspended •  Apps that want to run in the background stay here until

they're made Active again

24

Page 25: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Application Life Cycle •  Suspended

–  A Suspended app is frozen –  All the memory that app was

using while it was active is held just as it was •  If the user brings the app back to the Active state, it will

pick up right where it left off •  If the system needs more memory for an Active app,

any Suspended apps may be terminated (Not Running state) and their memory freed

25

Page 26: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Application Life Cycle •  Inactive

–  Temporary rest stop between 2 states –  The only ways an app can stay

Inactive for any length of time 1.  If the user is dealing with a system

prompt such as those shown for an incoming call or SMS message

2.  If the user has locked the screen

–  This state is basically a sort of limbo

26

Page 27: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

State-Change Notifications •  To manage changes between these states,

UIApplication defines a number of methods that its delegate can implement

•  UIApplication also defines a matching set of notification names –  This allows other objects besides the app

delegate to register for notifications when the app's state changes

27

Page 28: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Delegate Methods •  Delegate methods for tracking your

application's execution state and their corresponding notification names

28

Delegate Method" Notification Name"application:

didFinishLaunchingWithOptions: UIApplicationDidFinishLaunchingNotification"

applicationWillResignActive: UIApplicationWillResignActiveNotification"

applicationDidBecomeActive: UIApplicationDidBecomeActiveNotification"

applicationDidEnterBackground: UIApplicationDidEnterBackgroundNotification"

applicationWillEnterForeground: UIApplicationWillEnterForegroundNofication"

applicationWillTerminate: UIApplicationWillTerminateNotification"

Page 29: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Executing State Changes •  Active à Inactive

–  Use applicationWillResignActive: and/or UIApplicationWillResignActiveNotification

–  "Pause" your app's display •  Inactive à Background

–  Use applicationDidEnterBackground:/UIApplicationDidEnterBackgroundNotification

–  Release any resources –  Have about 5 seconds

•  Background à Inactive –  Use applicationWillEnterForeground:/

UIApplicationWillEnterForeground •  Inactive à Active

–  Use applicationDidBecomeActive:/UIApplicationDidBecomeActive

29

Page 30: ITP 342 Mobile App Dev - University of Southern …bcf.usc.edu/~trinagre/itp342/lectures/ITP342_GCD.pdf · ITP 342 Mobile App Dev Grand Central Dispatch ... • Works with Objective-C,

Project – State Lab •  Create a single view app project called

StateLab which will log messages to the console

•  A selector is simply Objective-C's way of referring to a method

•  Objective-C provides a handy built-in variable called _cmd that always contains the selector of the current method

•  The NSStringFromSelector function returns an NSString representation of a given selector

•  Shortcut for outputting the current method name

30

NSLog(@"%@", NSStringFromSelector(_cmd)); !