SlideShare a Scribd company logo
1 of 25
NSOperation
Павел Альбицкий
p.albitsky@gmail.com
Classes
• NSOperationQueue
• NSOperation
– NSOperation subclass
– NSBlockOperation
– NSInvocationOperation
NSOperationQueue
NSOperation *networkingOperation = ...
NSOperation *resizingOperation = ...
resizingOperation addDependency:networkingOperation];
NSOperationQueue *operationQueue = [NSOperationQueue new];
[operationQueue addOperation:networkingOperation];
[operationQueue addOperation:resizingOperation];
NSBlockOperation
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block1: %d, (%@)", i, [NSThread currentThread]);
}
}];
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.2];
NSLog(@"block2: %d, (%@)", i, [NSThread currentThread]);
}
}];
NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:block1];
[queue addOperation:block2];
NSLog(@"Here we go!");
2016-02-28 19:14:53.027 Here we go!
2016-02-28 19:14:53.237 block2: 0, (<NSThread: 0x610000067440>{number = 2, name = (null)})
2016-02-28 19:14:53.437 block2: 1, (<NSThread: 0x610000067440>{number = 2, name = (null)})
2016-02-28 19:14:53.528 block1: 0, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
2016-02-28 19:14:53.637 block2: 2, (<NSThread: 0x610000067440>{number = 2, name = (null)})
2016-02-28 19:14:53.838 block2: 3, (<NSThread: 0x610000067440>{number = 2, name = (null)})
2016-02-28 19:14:54.029 block1: 1, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
2016-02-28 19:14:54.040 block2: 4, (<NSThread: 0x610000067440>{number = 2, name = (null)})
2016-02-28 19:14:54.530 block1: 2, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
2016-02-28 19:14:55.030 block1: 3, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
2016-02-28 19:14:55.532 block1: 4, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
NSBlockOperation addExecutionBlock
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block1_1: %d", i);
}
}];
[block1 addExecutionBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block1_2: %d", i);
}
}];
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.2];
NSLog(@"block2: %d", i);
}
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:block1];
[queue addOperation:block2];
block2: 0
block2: 1
block1_2: 0
block1_1: 0
block2: 2
block2: 3
block1_2: 1
block1_1: 1
block2: 4
block1_2: 2
block1_1: 2
block1_1: 3
block1_2: 3
block1_1: 4
block1_2: 4
__block
int count1 = 7;
NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < count1; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block1: %d", i);
}
}];
__block int count2 = 3;
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
count2 = 7;
for (int i = 0; i < count2; ++i) {
[NSThread sleepForTimeInterval:0.2];
NSLog(@"block2: %d", i);
}
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[block1, block2] waitUntilFinished:YES];
NSLog(@"count2: %d", count2);
block2: 0
block2: 1
block1_1: 0
block2: 2
block2: 3
block1_1: 1
block2: 4
block2: 5
block2: 6
block1_1: 2
block1_1: 3
block1_1: 4
block1_1: 5
block1_1: 6
count2: 7
NSOperation start
NSBlockOperation *block1 = [[NSBlockOperation alloc] init];
[block1 addExecutionBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block1: %d (%@)", i, [NSThread currentThread]);
}
}];
NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < kIntervalCount; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"block2: %d (%@)", i, [NSThread currentThread]);
}
}];
[block1 start];
[block2 start];
NSLog(@“START");
block1: 0 (<NSThread: 0x600000061740>{number = 1, name = main})
block1: 1 (<NSThread: 0x600000061740>{number = 1, name = main})
block1: 2 (<NSThread: 0x600000061740>{number = 1, name = main})
block2: 0 (<NSThread: 0x600000061740>{number = 1, name = main})
block2: 1 (<NSThread: 0x600000061740>{number = 1, name = main})
block2: 2 (<NSThread: 0x600000061740>{number = 1, name = main})
START
NSInvocationOperation
- (void)runWithCount:(NSNumber *)count {
for (int i = 0; i < [count intValue]; ++i) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"operation: %d", i);
}
}
- (void)example5 {
NSInvocationOperation *invOp;
invOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(runWithCount:)
object:@(3)];
[invOp start];
}
NSInvocationOperation result
- (NSNumber *)sum {
int result;
for (int i = 0; i < kIntervalCount; ++i) {
result += i;
NSLog(@"result: %d", result);
}
return @(result);
}
- (void)example6 {
NSInvocationOperation *invOp;
invOp = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(sum)
object:nil];
[invOp start];
NSNumber *result = [invOp result];
}
NSOperation subclass
@interface CustomOperation : NSOperation
- (instancetype)initWithString:(NSString *)param;
@property(nonatomic, strong) NSString *param;
@end
@implementation CustomOperation
- (instancetype)initWithString:(NSString *)param {
self = [super init];
if (self) {
self.param = param;
}
return self;
}
- (void)main {
for (int i = 0; i < 5; ++i) {
[NSThread sleepForTimeInterval:.5];
NSLog(@"%@: %d", self.param, i);
}
}
@end
CustomOperation *op1 = [[CustomOperation alloc] initWithString:@"op1"];
CustomOperation *op2 = [[CustomOperation alloc] initWithString:@"op2"];
NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:op2];
[queue addOperation:op1];
op1: 0
op2: 0
op2: 1
op1: 1
op1: 2
op2: 2
op2: 3
op1: 3
op1: 4
op2: 4
CustomOperation
Configuring for concurrent execution
@interface CustomOperation () {
BOOL executing;
BOOL finished;
}
- (void)completeOperation;
@end
@implementation CustomOperation
- (instancetype)initWithString:(NSString *)param {
self = [super init];
if (self) {
executing = NO;
finished = NO;
self.param = param;
}
return self;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return finished;
}
- (void)start {
if ([self isCancelled]) {
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
[self willChangeValueForKey:@"isExecuting"];
[NSThread detachNewThreadSelector:@selector(main)
toTarget:self
withObject:nil];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)main {
@try {
// Do some work
[self completeOperation];
}
@catch (NSException *exception) {}
}
- (void)completeOperation {
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
State
ready → executing → finished
• ready
The isReady property contains the value true when the operation is ready to
execute now or false if there are still unfinished operations on which it is
dependent.
• executing
The isExecuting property must report the value true if the operation is working
on its task or false if it is not.
• finished
The isFinished key path lets clients know that an operation finished its task
successfully or was cancelled and is exiting.
• cancelled
The isCancelled key path lets clients know that the cancellation of an
operation was requested.
Cancelation
Once you add an operation to a queue, the operation is out
of your hands. The queue takes over and handles the
scheduling of that task. However, if you decide later that
you do not want to execute the operation after all—
because the user pressed a cancel button in a progress
panel or quit the application, for example—you can cancel
the operation to prevent it from consuming CPU time
needlessly.
• [NSOperation cancel]
• [NSOperationQueue cancellAllOperations]
NSOperationQueuePriority
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
NSOperation *op = ...
op.queuePriority = NSOperationQueuePriorityHigh;
NSQualityOfService
typedef NS_ENUM(NSInteger, NSQualityOfService) {
NSQualityOfServiceUserInteractive = 0x21,
NSQualityOfServiceUserInitiated = 0x19,
NSQualityOfServiceUtility = 0x11,
NSQualityOfServiceBackground = 0x09,
NSQualityOfServiceDefault = -1
} NS_ENUM_AVAILABLE(10_10, 8_0);
NSOperation *op = ...
op.qualityOfService = NSOperationQualityOfServiceUtility;
// threadPriority - deprecated
NSQualityOfService
• UserInteractive
Used for work directly involved in providing an interactive UI. For example,
processing control events or drawing to the screen.
• UserInitiated
Used for performing work that has been explicitly requested by the user, and for
which results must be immediately presented in order to allow for further user
interaction. For example, loading an email after a user has selected it in a message
list.
• Utility
Used for performing work which the user is unlikely to be immediately waiting for
the results. This work may have been requested by the user or initiated
automatically, and often operates at user-visible timescales using a non-modal
progress indicator. For example, periodic content updates or bulk file operations,
such as media import.
• Background
Used for work that is not user initiated or visible. In general, a user is unaware
that this work is even happening. For example, pre-fetching content, search
indexing, backups, or syncing of data with external systems.
• Default
Indicates no explicit quality of service information. Whenever possible, an
appropriate quality of service is determined from available sources.
completionBlock
CustomOperation *op = [[CustomOperation alloc] initWithString:@"op1"];
op.completionBlock = ^{
NSLog(@"completed: %@", [NSThread currentThread]);
};
[op start];
NSLog(@"isConcurrent: %d", op.isConcurrent);
isConcurrent: 1
op1: 0 (<NSThread: 0x608000068680>{number = 2, name = (null)})
op1: 1 (<NSThread: 0x608000068680>{number = 2, name = (null)})
op1: 2 (<NSThread: 0x608000068680>{number = 2, name = (null)})
op1: 3 (<NSThread: 0x608000068680>{number = 2, name = (null)})
op1: 4 (<NSThread: 0x608000068680>{number = 2, name = (null)})
completed: <NSThread: 0x618000076600>{number = 3, name = (null)}
NSOperationQueue
• Serial
queue.maxConcurrentOperationCount = 1;
• Concurrent
queue.maxConcurrentOperationCount = 6;
static const NSInteger
NSOperationQueueDefaultMaxConcurrentOperationCount = -1;
NSOperationQueue
@interface NSOperationQueue : NSObject
- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;
- (void)addOperationWithBlock:(void (^)(void))block;
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;
@property (readonly) NSUInteger operationCount;
- (void)waitUntilAllOperationsAreFinished;
@property (getter=isSuspended) BOOL suspended;
@property (nullable, copy) NSString *name;
@property NSQualityOfService qualityOfService;
@end
KVO-Compliant Properties
• isCancelled - read-only
• isAsynchronous - read-only
• isExecuting - read-only
• isFinished - read-only
• isReady - read-only
• dependencies - read-only
• queuePriority - readable and writable
• completionBlock - readable and writable
NSOperation VS GCD
Grand Central Dispatch
• Delayed calls
• Performance
• Low-level
• Functional programming
NSOperation
• Dependency
• Priority queue and QoS
• Cancelation
• State
• Object oriented programming
Спасибо за внимание!
Павел Альбицкий
p.albitsky@gmail.com

More Related Content

What's hot

Maximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestMaximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestPythian
 
what is_the_best_way_of_method_swizzling
what is_the_best_way_of_method_swizzlingwhat is_the_best_way_of_method_swizzling
what is_the_best_way_of_method_swizzlingAkira Miki
 
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDY
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDYDATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDY
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDYMalikireddy Bramhananda Reddy
 
Java 7 at SoftShake 2011
Java 7 at SoftShake 2011Java 7 at SoftShake 2011
Java 7 at SoftShake 2011julien.ponge
 
Java 7 JUG Summer Camp
Java 7 JUG Summer CampJava 7 JUG Summer Camp
Java 7 JUG Summer Campjulien.ponge
 
Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Chih-Hsuan Kuo
 
RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)Yoshifumi Kawai
 
The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202Mahmoud Samir Fayed
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in RustChih-Hsuan Kuo
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispDamien Cassou
 
Use C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in GeckoUse C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in GeckoChih-Hsuan Kuo
 
Java Performance Puzzlers
Java Performance PuzzlersJava Performance Puzzlers
Java Performance PuzzlersDoug Hawkins
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...julien.ponge
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189Mahmoud Samir Fayed
 

What's hot (20)

Qt Rest Server
Qt Rest ServerQt Rest Server
Qt Rest Server
 
Maximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digestMaximizing SQL Reviews and Tuning with pt-query-digest
Maximizing SQL Reviews and Tuning with pt-query-digest
 
Python Async IO Horizon
Python Async IO HorizonPython Async IO Horizon
Python Async IO Horizon
 
what is_the_best_way_of_method_swizzling
what is_the_best_way_of_method_swizzlingwhat is_the_best_way_of_method_swizzling
what is_the_best_way_of_method_swizzling
 
Microkernel Development
Microkernel DevelopmentMicrokernel Development
Microkernel Development
 
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDY
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDYDATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDY
DATASTRUCTURES PPTS PREPARED BY M V BRAHMANANDA REDDY
 
Java 7 at SoftShake 2011
Java 7 at SoftShake 2011Java 7 at SoftShake 2011
Java 7 at SoftShake 2011
 
Java 7 JUG Summer Camp
Java 7 JUG Summer CampJava 7 JUG Summer Camp
Java 7 JUG Summer Camp
 
Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36Effective Modern C++ - Item 35 & 36
Effective Modern C++ - Item 35 & 36
 
Process management
Process managementProcess management
Process management
 
RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity(English)
 
The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202The Ring programming language version 1.8 book - Part 31 of 202
The Ring programming language version 1.8 book - Part 31 of 202
 
Ownership System in Rust
Ownership System in RustOwnership System in Rust
Ownership System in Rust
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common Lisp
 
Use C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in GeckoUse C++ to Manipulate mozSettings in Gecko
Use C++ to Manipulate mozSettings in Gecko
 
Java 7 LavaJUG
Java 7 LavaJUGJava 7 LavaJUG
Java 7 LavaJUG
 
Java Performance Puzzlers
Java Performance PuzzlersJava Performance Puzzlers
Java Performance Puzzlers
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
 
The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88The Ring programming language version 1.3 book - Part 59 of 88
The Ring programming language version 1.3 book - Part 59 of 88
 
The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189The Ring programming language version 1.6 book - Part 28 of 189
The Ring programming language version 1.6 book - Part 28 of 189
 

Similar to NSOperation objective-c

連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」matuura_core
 
The Ring programming language version 1.7 book - Part 93 of 196
The Ring programming language version 1.7 book - Part 93 of 196The Ring programming language version 1.7 book - Part 93 of 196
The Ring programming language version 1.7 book - Part 93 of 196Mahmoud Samir Fayed
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special CasesCiklum Ukraine
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone DevelopmentGiordano Scalzo
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...DroidConTLV
 
Zabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensZabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensNETWAYS
 
Коварный code type ITGM #9
Коварный code type ITGM #9Коварный code type ITGM #9
Коварный code type ITGM #9Andrey Zakharevich
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testingsgleadow
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test DriveGraham Lee
 
Hacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from PerlHacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from Perltypester
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The LandingHaci Murat Yaman
 
Working with AFNetworking
Working with AFNetworkingWorking with AFNetworking
Working with AFNetworkingwaynehartman
 
Project single cyclemips processor_verilog
Project single cyclemips processor_verilogProject single cyclemips processor_verilog
Project single cyclemips processor_verilogHarsha Yelisala
 
iOS Unit test getting stared
iOS Unit test getting starediOS Unit test getting stared
iOS Unit test getting staredLiyao Chen
 

Similar to NSOperation objective-c (20)

連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
The Ring programming language version 1.7 book - Part 93 of 196
The Ring programming language version 1.7 book - Part 93 of 196The Ring programming language version 1.7 book - Part 93 of 196
The Ring programming language version 1.7 book - Part 93 of 196
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special Cases
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
Zabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensZabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet Mens
 
Live Updating Swift Code
Live Updating Swift CodeLive Updating Swift Code
Live Updating Swift Code
 
Коварный code type ITGM #9
Коварный code type ITGM #9Коварный code type ITGM #9
Коварный code type ITGM #9
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testing
 
I os 06
I os 06I os 06
I os 06
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test Drive
 
Hacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from PerlHacking Mac OSX Cocoa API from Perl
Hacking Mac OSX Cocoa API from Perl
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 
Working with AFNetworking
Working with AFNetworkingWorking with AFNetworking
Working with AFNetworking
 
Marat-Slides
Marat-SlidesMarat-Slides
Marat-Slides
 
3
33
3
 
Project single cyclemips processor_verilog
Project single cyclemips processor_verilogProject single cyclemips processor_verilog
Project single cyclemips processor_verilog
 
Testing (eng)
Testing (eng)Testing (eng)
Testing (eng)
 
unit5 uc.pptx
unit5 uc.pptxunit5 uc.pptx
unit5 uc.pptx
 
iOS Unit test getting stared
iOS Unit test getting starediOS Unit test getting stared
iOS Unit test getting stared
 

NSOperation objective-c

  • 2. Classes • NSOperationQueue • NSOperation – NSOperation subclass – NSBlockOperation – NSInvocationOperation
  • 3. NSOperationQueue NSOperation *networkingOperation = ... NSOperation *resizingOperation = ... resizingOperation addDependency:networkingOperation]; NSOperationQueue *operationQueue = [NSOperationQueue new]; [operationQueue addOperation:networkingOperation]; [operationQueue addOperation:resizingOperation];
  • 5. NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block1: %d, (%@)", i, [NSThread currentThread]); } }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.2]; NSLog(@"block2: %d, (%@)", i, [NSThread currentThread]); } }]; NSOperationQueue *queue = [NSOperationQueue new]; [queue addOperation:block1]; [queue addOperation:block2]; NSLog(@"Here we go!"); 2016-02-28 19:14:53.027 Here we go! 2016-02-28 19:14:53.237 block2: 0, (<NSThread: 0x610000067440>{number = 2, name = (null)}) 2016-02-28 19:14:53.437 block2: 1, (<NSThread: 0x610000067440>{number = 2, name = (null)}) 2016-02-28 19:14:53.528 block1: 0, (<NSThread: 0x610000069f40>{number = 3, name = (null)}) 2016-02-28 19:14:53.637 block2: 2, (<NSThread: 0x610000067440>{number = 2, name = (null)}) 2016-02-28 19:14:53.838 block2: 3, (<NSThread: 0x610000067440>{number = 2, name = (null)}) 2016-02-28 19:14:54.029 block1: 1, (<NSThread: 0x610000069f40>{number = 3, name = (null)}) 2016-02-28 19:14:54.040 block2: 4, (<NSThread: 0x610000067440>{number = 2, name = (null)}) 2016-02-28 19:14:54.530 block1: 2, (<NSThread: 0x610000069f40>{number = 3, name = (null)}) 2016-02-28 19:14:55.030 block1: 3, (<NSThread: 0x610000069f40>{number = 3, name = (null)}) 2016-02-28 19:14:55.532 block1: 4, (<NSThread: 0x610000069f40>{number = 3, name = (null)})
  • 6. NSBlockOperation addExecutionBlock NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block1_1: %d", i); } }]; [block1 addExecutionBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block1_2: %d", i); } }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.2]; NSLog(@"block2: %d", i); } }]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:block1]; [queue addOperation:block2]; block2: 0 block2: 1 block1_2: 0 block1_1: 0 block2: 2 block2: 3 block1_2: 1 block1_1: 1 block2: 4 block1_2: 2 block1_1: 2 block1_1: 3 block1_2: 3 block1_1: 4 block1_2: 4
  • 7. __block int count1 = 7; NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < count1; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block1: %d", i); } }]; __block int count2 = 3; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ count2 = 7; for (int i = 0; i < count2; ++i) { [NSThread sleepForTimeInterval:0.2]; NSLog(@"block2: %d", i); } }]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperations:@[block1, block2] waitUntilFinished:YES]; NSLog(@"count2: %d", count2); block2: 0 block2: 1 block1_1: 0 block2: 2 block2: 3 block1_1: 1 block2: 4 block2: 5 block2: 6 block1_1: 2 block1_1: 3 block1_1: 4 block1_1: 5 block1_1: 6 count2: 7
  • 8. NSOperation start NSBlockOperation *block1 = [[NSBlockOperation alloc] init]; [block1 addExecutionBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block1: %d (%@)", i, [NSThread currentThread]); } }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < kIntervalCount; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"block2: %d (%@)", i, [NSThread currentThread]); } }]; [block1 start]; [block2 start]; NSLog(@“START"); block1: 0 (<NSThread: 0x600000061740>{number = 1, name = main}) block1: 1 (<NSThread: 0x600000061740>{number = 1, name = main}) block1: 2 (<NSThread: 0x600000061740>{number = 1, name = main}) block2: 0 (<NSThread: 0x600000061740>{number = 1, name = main}) block2: 1 (<NSThread: 0x600000061740>{number = 1, name = main}) block2: 2 (<NSThread: 0x600000061740>{number = 1, name = main}) START
  • 9. NSInvocationOperation - (void)runWithCount:(NSNumber *)count { for (int i = 0; i < [count intValue]; ++i) { [NSThread sleepForTimeInterval:0.5]; NSLog(@"operation: %d", i); } } - (void)example5 { NSInvocationOperation *invOp; invOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runWithCount:) object:@(3)]; [invOp start]; }
  • 10. NSInvocationOperation result - (NSNumber *)sum { int result; for (int i = 0; i < kIntervalCount; ++i) { result += i; NSLog(@"result: %d", result); } return @(result); } - (void)example6 { NSInvocationOperation *invOp; invOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(sum) object:nil]; [invOp start]; NSNumber *result = [invOp result]; }
  • 12. @interface CustomOperation : NSOperation - (instancetype)initWithString:(NSString *)param; @property(nonatomic, strong) NSString *param; @end @implementation CustomOperation - (instancetype)initWithString:(NSString *)param { self = [super init]; if (self) { self.param = param; } return self; } - (void)main { for (int i = 0; i < 5; ++i) { [NSThread sleepForTimeInterval:.5]; NSLog(@"%@: %d", self.param, i); } } @end
  • 13. CustomOperation *op1 = [[CustomOperation alloc] initWithString:@"op1"]; CustomOperation *op2 = [[CustomOperation alloc] initWithString:@"op2"]; NSOperationQueue *queue = [NSOperationQueue new]; [queue addOperation:op2]; [queue addOperation:op1]; op1: 0 op2: 0 op2: 1 op1: 1 op1: 2 op2: 2 op2: 3 op1: 3 op1: 4 op2: 4 CustomOperation
  • 14. Configuring for concurrent execution @interface CustomOperation () { BOOL executing; BOOL finished; } - (void)completeOperation; @end @implementation CustomOperation - (instancetype)initWithString:(NSString *)param { self = [super init]; if (self) { executing = NO; finished = NO; self.param = param; } return self; } - (BOOL)isConcurrent { return YES; } - (BOOL)isExecuting { return executing; } - (BOOL)isFinished { return finished; } - (void)start { if ([self isCancelled]) { [self willChangeValueForKey:@"isFinished"]; finished = YES; [self didChangeValueForKey:@"isFinished"]; return; } [self willChangeValueForKey:@"isExecuting"]; [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; executing = YES; [self didChangeValueForKey:@"isExecuting"]; } - (void)main { @try { // Do some work [self completeOperation]; } @catch (NSException *exception) {} } - (void)completeOperation { [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; executing = NO; finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"]; }
  • 15. State ready → executing → finished • ready The isReady property contains the value true when the operation is ready to execute now or false if there are still unfinished operations on which it is dependent. • executing The isExecuting property must report the value true if the operation is working on its task or false if it is not. • finished The isFinished key path lets clients know that an operation finished its task successfully or was cancelled and is exiting. • cancelled The isCancelled key path lets clients know that the cancellation of an operation was requested.
  • 16. Cancelation Once you add an operation to a queue, the operation is out of your hands. The queue takes over and handles the scheduling of that task. However, if you decide later that you do not want to execute the operation after all— because the user pressed a cancel button in a progress panel or quit the application, for example—you can cancel the operation to prevent it from consuming CPU time needlessly. • [NSOperation cancel] • [NSOperationQueue cancellAllOperations]
  • 17. NSOperationQueuePriority typedef NS_ENUM(NSInteger, NSOperationQueuePriority) { NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8 }; NSOperation *op = ... op.queuePriority = NSOperationQueuePriorityHigh;
  • 18. NSQualityOfService typedef NS_ENUM(NSInteger, NSQualityOfService) { NSQualityOfServiceUserInteractive = 0x21, NSQualityOfServiceUserInitiated = 0x19, NSQualityOfServiceUtility = 0x11, NSQualityOfServiceBackground = 0x09, NSQualityOfServiceDefault = -1 } NS_ENUM_AVAILABLE(10_10, 8_0); NSOperation *op = ... op.qualityOfService = NSOperationQualityOfServiceUtility; // threadPriority - deprecated
  • 19. NSQualityOfService • UserInteractive Used for work directly involved in providing an interactive UI. For example, processing control events or drawing to the screen. • UserInitiated Used for performing work that has been explicitly requested by the user, and for which results must be immediately presented in order to allow for further user interaction. For example, loading an email after a user has selected it in a message list. • Utility Used for performing work which the user is unlikely to be immediately waiting for the results. This work may have been requested by the user or initiated automatically, and often operates at user-visible timescales using a non-modal progress indicator. For example, periodic content updates or bulk file operations, such as media import. • Background Used for work that is not user initiated or visible. In general, a user is unaware that this work is even happening. For example, pre-fetching content, search indexing, backups, or syncing of data with external systems. • Default Indicates no explicit quality of service information. Whenever possible, an appropriate quality of service is determined from available sources.
  • 20. completionBlock CustomOperation *op = [[CustomOperation alloc] initWithString:@"op1"]; op.completionBlock = ^{ NSLog(@"completed: %@", [NSThread currentThread]); }; [op start]; NSLog(@"isConcurrent: %d", op.isConcurrent); isConcurrent: 1 op1: 0 (<NSThread: 0x608000068680>{number = 2, name = (null)}) op1: 1 (<NSThread: 0x608000068680>{number = 2, name = (null)}) op1: 2 (<NSThread: 0x608000068680>{number = 2, name = (null)}) op1: 3 (<NSThread: 0x608000068680>{number = 2, name = (null)}) op1: 4 (<NSThread: 0x608000068680>{number = 2, name = (null)}) completed: <NSThread: 0x618000076600>{number = 3, name = (null)}
  • 21. NSOperationQueue • Serial queue.maxConcurrentOperationCount = 1; • Concurrent queue.maxConcurrentOperationCount = 6; static const NSInteger NSOperationQueueDefaultMaxConcurrentOperationCount = -1;
  • 22. NSOperationQueue @interface NSOperationQueue : NSObject - (void)addOperation:(NSOperation *)op; - (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait; - (void)addOperationWithBlock:(void (^)(void))block; @property (readonly, copy) NSArray<__kindof NSOperation *> *operations; @property (readonly) NSUInteger operationCount; - (void)waitUntilAllOperationsAreFinished; @property (getter=isSuspended) BOOL suspended; @property (nullable, copy) NSString *name; @property NSQualityOfService qualityOfService; @end
  • 23. KVO-Compliant Properties • isCancelled - read-only • isAsynchronous - read-only • isExecuting - read-only • isFinished - read-only • isReady - read-only • dependencies - read-only • queuePriority - readable and writable • completionBlock - readable and writable
  • 24. NSOperation VS GCD Grand Central Dispatch • Delayed calls • Performance • Low-level • Functional programming NSOperation • Dependency • Priority queue and QoS • Cancelation • State • Object oriented programming
  • 25. Спасибо за внимание! Павел Альбицкий p.albitsky@gmail.com