ios alkalmazásfejlesztés Koltai Róbert robert.koltai@ponte.hu
Mi az a block? Utasítások sorozata { }-ek között, amit egy objektumként tuduk kezelni. ios 4.0 és Mac OSX 10.6 óta 2
Egy példa a felépítésére [exampledictionary enumeratekeysandobjectsusingblock:^(id key, id value, BOOL *stop) { NSLog(@"%@ : %@", key, value); if ([key isequaltostring:@"stopkey"]) { *stop = YES; } }]; Minden block ^-vel kezdődik Lehet visszatérési értéke Lehetnek bemenő paraméterei (<#type#> <#name#>,..) { utasítások } 3
http://fuckingblocksyntax.com/ 4
Lokális változók is használhatóak a block-on belül int stopvalue = 42; [exampledictionary enumeratekeysandobjectsusingblock:^(id key, id value, BOOL *stop) { NSLog(@"%@ : %@", key, value); if ([key isequaltostring:@ stopkey"] [value intvalue] == stopvalue) { *stop = YES; } }]; DE csak read-only block BOOL stoppedearly = NO; int stopvalue = 42; [exampledictionary enumeratekeysandobjectsusingblock:^(id key, id value, BOOL *stop) { NSLog(@"%@ : %@", key, value); if ([key isequaltostring:@ stopkey"] [value intvalue] == stopvalue) { stoppedearly = YES; //HIBA * s t o p = YES; } }]; 5
Kivéve, ha ellátjuk egy block storage type-al block int stopvalue = 42; [exampledictionary enumeratekeysandobjectsusingblock:^(id key, id value, BOOL *stop) { NSLog(@"%@ : %@", key, value); if ([key isequaltostring:@ stopkey"] [value intvalue] == stopvalue) { stoppedearly = YES; //Ebben az esetben már helyes * s t o p = YES; } }]; Vagy, ha instance variable (_name) De ezek elérésére a setter-eket és a getter-eket használjuk 6
Mi van azokkal a változókkal, amiknek üzenetet küldünk? NSString *stopkey = @"stopkey"; block BOOL stoppedearly = NO; int stopvalue = 42; [exampledictionary enumeratekeysandobjectsusingblock:^(id key, id value, BOOL *stop) { if ([stopkey isequaltostring:key] ([value doublevalue] == stopvalue)) { *stop = YES; stoppedearly = YES; } }]; if (stoppedearly) NSLog(@"I stopped logging dictionary values early ); Ebben az esetben a stopkey a block lefutásáig automatikusan egy strong pointer lesz. Mert a block lefutásáig nem szabadulhet fel. 7
Készítsünk egy olyan változót, amibe majd egy block-ot teszünk Hogy bele tudjunk tenni egy változóba egy block-ot, előbb meg kell határoznunk a változó típusát. Szerkezet typedef <#returntype#>(^<#name#>)(<#arguments#>); Példa typedef double (^squareblock)(double op); 8
Készítsünk egy olyan változót, amibe majd egy block-ot teszünk squareblock square; square = ^(double op) { return op * op; }; NSLog(@"square of five: %f", square(5)); Nem kötelező a typedef, a következő módon is definiálhatunk egy block-ot double (^square)(double op) = ^(double op) { return op * op; }; NSLog(@"square of five: %f", square(5)); 9
Lecture 8 Slides.pdf / 21-28. dia 10
Hol használunk block-okak? Enumeration View animations Sorting Notifications Callbacks(Error handlers, Complition handlers) Multithreading (GCD API) 11
GCD Grand Central Dispatch Dispatch queues are a C-based mechanism for executing custom tasks A dispatch queue executes tasks either serially or concurrently but always in a first-in, first-out order A serial dispatch queue runs only one task at a time, waiting until that task is complete before dequeuing and starting a new one a concurrent dispatch queue starts as many tasks as it can without waiting for already started tasks to finish. 12
GCD Dispatch queues have other benefits: They provide a straightforward and simple programming interface. They offer automatic and holistic thread pool management. They provide the speed of tuned assembly. They are much more memory efficient (because thread stacks do not linger in application memory). They do not trap to the kernel under load. The asynchronous dispatching of tasks to a dispatch queue cannot deadlock the queue. They scale gracefully under contention. Serial dispatch queues offer a more efficient alternative to locks and other synchronization primitives. 13
Operation Queues Egy operation queue a Cococa-s megfelelője a dispatch queue-nak NSOperationQueue osztály Kibővíti a first-in, first-out rendezési elver (függőségek, prioritás, KVO) Egy operation queue-ba NSOperation példányokat tehetünk Az NSOperation egy abstract base class 14
Operations Foundation framework-ben 3 típusú operationt találunk: NSInvocationOperation, NSBlockOperation, NSOperation NSInvocationOperation Akkor hasznájuk, ha nagy számú egyedi operation-t ugyanarra a feladatra használni NSInvocationOperation *theop = [[NSInvocationOperation alloc] initwithtarget:self selector:@selector(mytaskmethod:) object:data]; - (void)mytaskmethod:(id)data { // Perform the task. } 15
Operations Foundation framework-ben 3 típusú operationt találunk: NSInvocationOperation, NSBlockOperation, NSOperation NSBlockOperation Egy objektum orientált wrapper-t nyújt a dispatch queue-ra NSBlockOperation *theop = [NSBlockOperation blockoperationwithblock: ^{ // Do some work. }]; 16
Operations Foundation framework-ben 3 típusú operationt találunk: NSInvocationOperation, NSBlockOperation, NSOperation NSOperation Ha az NSInvocationOperation és a NSBlockOperation nem elégítik ki az igényeket, akkor az NSOperation-ből készítünk subclass-t Minden operation objektumnak meg kell valósítania a következő metódusokat Custom initialization method main 17
Operations @interface MyNonConcurrentOperation : NSOperation @property (strong) id mydata; -(id)initwithdata:(id)data; @end @implementation MyNonConcurrentOperation - (id)initwithdata:(id)data { if (self = [super init]) self.mydata = data; return self; } - (void)main { @try { // Do some work on mydata and report the results. } @catch(...) { // Do not rethrow exceptions. } } @end 18
Nézzük meg a használatukat