-
Notifications
You must be signed in to change notification settings - Fork 3
iOS Concurrency
Kevin Leong edited this page Jan 7, 2017
·
11 revisions
The following example is an app with the following UI elements:
- A button to add a job to a serial queue.
- A button to add a job to the default global concurrent queue.
- A text field to display results when a job has been completed.
import "MyViewController.h"
@interface MyViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextView *myTextView;
@property (weak, nonatomic) IBOutlet UIButton *serialButton;
@property (weak, nonatomic) IBOutlet UIButton *concurrentButton;
// Must be publically available for it to be called from another thread.
-(void)delayAndDisplay:(NSString*) queueType;
@end
@implementation MyViewController
- (void)sendJobToSerialQueue {
// Creates a serial queue with a specified identifier.
dispatch_queue_t serialQueue =
dispatch_queue_create("mySerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
[self delayAndDisplay:@"Serial"];
});
}
-(void)sendJobToConcurrentQueue {
/**
Gets a reference to one of the global concurrent queues.
Global queues ranked by highest priority first:
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
*/
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
[self delayAndDisplay:@"Concurrent"];
});
}
-(void)delayAndDisplay:(NSString *)queueType {
// Sleep
[NSThread sleepForTimeInterval: 3.0];
/**
All UI updates must be done on the main thread, which
can be referenced via `dispatch_get_main_queue`.
*/
dispatch_async(dispatch_get_main_queue(), ^{
NSString *text = [[self myTextView] text];
[[self myTextView] setText:[NSString stringWithFormat:@"%@\n%@", text, queueType]];
});
}
- (IBAction)onButtonTap:(id)sender {
if(sender == _serialButton) {
[self sendJobToSerialQueue];
}
else {
[self sendJobToConcurrentQueue];
}
}
@end
- Apple Developer
- Creating dispatch queues in Swift 3 - Stack Overflow
- Grand Central Dispatch - Ray Wenderlich
- GCD 101 - Hacking With Swift
The example before has a single button and a text field that logs are printed to.
#import "MyViewController.h"
@interface MyViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextView *myTextView;
@property (weak, nonatomic) IBOutlet UIButton *performJobButton;
-(void)display:(NSString*) queueType withDelay:(NSTimeInterval) delayInSeconds;
@end
@implementation MyViewController
- (IBAction)onButtonTap:(id)sender {
// Create an operation queue
NSOperationQueue *queue = [NSOperationQueue new];
// Convenience method to add a block operation to the queue
[queue addOperationWithBlock:^{
[self display:@"Simple job done" withDelay:1.0];
}];
/**
For granular control over operations, NSOperation instances must
be created.
In this example, secondPart is dependent on firstPart and will
not be executed until it's dependency is complete.
*/
NSOperation *firstPart = [NSBlockOperation blockOperationWithBlock:^{
[self display:@"First part done" withDelay:1.0];
}];
// Add a block to be executed on operation completion.
firstPart.completionBlock = ^{
[self display:@"boo" withDelay:1.0];
};
NSOperation *secondPart = [NSBlockOperation blockOperationWithBlock:^{
[self display:@"Second part done" withDelay:2.0];
}];
// Make the second part a dependency of the first part.
[secondPart addDependency:firstPart];
// Can be done in any order, since a dependency between
// the two operations has been established.
[queue addOperation:secondPart];
[queue addOperation:firstPart];
}
-(void)display:(NSString *) message withDelay:(NSTimeInterval) delayInSeconds {
[NSThread sleepForTimeInterval: delayInSeconds];
NSString *dateString = [[NSDate date] description];
dispatch_async(dispatch_get_main_queue(), ^{
NSString *text = [[self myTextView] text];
[[self myTextView] setText:[NSString stringWithFormat:@"%@\n%@\t%@", text, message, dateString]];
});
}
@end