czwartek, 15 stycznia 2015

iOS, a co to jest - odcinek 13: współbieżność

W dniu dzisiejszym najwięcej o współbieżności. Mamy API do kolejek wykonujących taski sekwencyjnie i równolegle (w tym z uwzględnieniem zależności).  Forma wydaje się dość szkolna, nie ma takiego uproszczenia kodu jak w async,  ale używający od razu wie, co robi.  Zresztą w aplikacjach XAML też jawnie czasami musimy powiedzieć, w jakim wątku chcemy coś wykonać (nie wspominając o różnej obsłudze współbieżności w platformie .NET).

 

Współbieżność

Bloki

__block – zmienna modyfikowana w bloku

 

Kolejki Dispatch

Dwa typy

  • Serial (jedno zadanie w danym czasie)
    • możemy definiować własne
    • wykonują kod w wątkach w tle
  • Concurrent (wiele zadań równocześnie)
    • dispatch_get_global_queue - referencja do kolejek
    • cztery globalne kolejki w każdej aplikacji
      • DISPATCH_QUEUE_PRIORITY_HIGH
      • DISPATCH_QUEUE_PRIORITY_DEFAULT
      • DISPATCH_QUEUE_PRIORITY_LOW
      • DISPATCH_QUEUE_PRIORITY_BACKGROUND
    • wykonywanie kodu w wątkach w tle
    • liczba tasków wykonywanych równolegle jest zarządzana przez system

Dodawanie tasków do kolejki

dispatch_queue_t queue;

queue = dispatch_queue_create(“xxx”, DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{

});

 

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{

});

 

Kolejki Operation

?

  • Nie FIFO, jak w Dispatch
  • NSOperationQueue
  • zawsze wykonują się równoległe

NSOperation

  • opakowuje blok kodu do wykonania
  • dodatkowe funkcjonalności
    • - (void) addDependency: (NSOperation *) operation
    • - (void) setCompletionBlock: (void(^)(void)) block
    • - (void)  setQueuePriority: (NSOperationQueuePriority) priority
  • 2 podklasy
    • NSInvocationOperation
    • NSBlockOperation
  • własne podklasy
  • obserwacja klucz-wartość
    • isCancelled
    • isConcurrent
    • isExecuting
    • isFinished
    • isReady
    • dependencies
    • queuePriority
    • completionBlock
  • zależności od innych operacji
  • priorytet wykonania
  • możliwość anulowania
  • bloki Completed

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock: ^{

}];

[operation setQueuePriority: NSOperationQueuePriorityHigh];

[operation setThreadPriority: 0.5] //inny sposób określenia priorytetu

[operation setCompletionBlock: ^{

}];

[operation2 addDependency: operation];

[operation cancel];

 

[operation  addObserver: self   forKeyPath: @”isCancelled”

  options: NSKeyValueObservingOptionNew

  context: (__bridge void *) (zmienna)];

- (void) observeValueForKeyPath: (NSString *) keyPath

                ofObject: (id) object   change: (NSDictionary *) change

                context:  (void *) cotext {

}

 

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

[operationQueue addOperationWithBlock: ^{

       //ten sam kod, co przy kolejkach Dispatch, w tym część kodu z wywołaniem w wątku UI

}];

[operationQueue addOperation: operation];  //dodanie NSBlockOperation

[operationQueue cancelAllOperations];

 

Tworzenie podklas NSOperation

[operation start] //bezpośrednie wywołanie operacji, domyślnie synchronicznie z wątkiem wołającym, nie równolegle

Operacje nierównoległe

  • dziedziczą po NSOperation
  • łatwiejsze do implementacji
  • dodana do kolejki wykonuje się równolegle
  • możliwość anulowania

@interface XOperation: NSOperation

@end

@implementation XOperation

- (void) main {

         //praca

        // sprawdzenie anulowania:  [self  isCancelled]

        // praca

        // w razie potrzeby powtórzenie

}

@end

 

Deploying

Od XCode 5 można z jego poziomu wygodnie tworzyć profile, identyfikatory, rejestrować urządzenia itd.

Profile

  • developerski
  • dystrybucyjny - ad hoc i do app store (certyfikaty do add hoc i app store  mogą być te same)

.ipa to .zip  (podobnie jak .xap czy .appx)

 

Debugowanie

Wyjątki i sygnały

di –s  rejestr - odkodowanie informacji

NSSetUncaughtExceptionHandler / Signal handler  - bardziej globalne przechwytywanie

AppDelegate:

NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);

signal(SIGSEV, SignalHandler);

void UncaughtExceptionHandler(NSException *exception)

{

         void* myCallStack[128];

         int frames = backtrace(myCallStack, 128);

         char **btstrings = backtrace_symbols(myCallStack, frames);

         …

         exception.name

         exception.reason

         exception.userInfo

}

void SignalHandler(int signal)

{

         //ten sam kod wyciągania stosu

}

Device Logs

Rodzaje breakpointów

  • General
  • Logging
  • Conditional
  • Exception
  • Symbolic (gdy jakaś funkcja / metoda zacznie się wykonywać)
  • Executing

Brak komentarzy: