Slide 1

Slide 1 text

if (error) { // TODO } Sven Titgemeyer 15.09.2018

Slide 2

Slide 2 text

Wer bin ich? • iOS Enthusiast • Freelancer • große Projekte • Student • kleine Projekte • Open Source (iCarambaa) @s_titgemeyer

Slide 3

Slide 3 text

- (void)someMethod { NSURLSession *session = [NSURLSession sharedSession]; [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { // TODO return; } // Continue with success case. }]; }

Slide 4

Slide 4 text

func someFunction() { URLSession.shared.dataTask(with: url) { (data, response, error) in guard let data = data else { // TODO return } // Continue... } }

Slide 5

Slide 5 text

func someFunction() { URLSession.shared.dataTask(with: url) { (data, response, error) in guard let data = data else { print("Error: \(error!)") return } // Continue... } }

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Agenda • Error Handling Patterns • Was macht der Mac? • Error erstellen • Error weiterreichen • Error anzeigen Metal Systemframeworks Andere Frameworks Eigene Frameworks App Error Error

Slide 8

Slide 8 text

UIAlertView

Slide 9

Slide 9 text

UIAlertView ^(NSData *data, NSURLResponse *response, NSError *error) { if (data) { // Success case... } else { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; }); } }

Slide 10

Slide 10 text

UIAlertView ✗

Slide 11

Slide 11 text

UIAlertController

Slide 12

Slide 12 text

UIAlertController -[UIAlertController show] ✗

Slide 13

Slide 13 text

UIAlertController •Ein Alert ist ein View Controller •Wollen wir einen View Controller an x verschiedenen Stellen initialisieren? •… oder innerhalb eines Models? •Fragen wir Stackoverflow! •“Present UIAlertController without View Controller”

Slide 14

Slide 14 text

UIAlertController

Slide 15

Slide 15 text

UIAlertController • Eigene Alert über oder unter Systemalerts? • Window teilen oder kriegt jedes ein eigenes? • Mehrere Alerts übereinander? Kurz: Don’t

Slide 16

Slide 16 text

macOS

Slide 17

Slide 17 text

macOS @interface NSResponder(NSErrorPresentation) - (BOOL)presentError:(NSError *)error; - (NSError *)willPresentError:(NSError *)error; @end

Slide 18

Slide 18 text

macOS dispatch_async(dispatch_get_main_queue(), ^{ BOOL didRecover = [self presentError:error]; if (didRecover) { // Retry. } }

Slide 19

Slide 19 text

macOS

Slide 20

Slide 20 text

NSError Code Domain NSLocalizedDescriptionKey NSLocalizedFailureErrorKey NSLocalizedFailureReasonErrorKey NSLocalizedRecoverySuggestionErrorKey … Beispiel: NSFileWriteOutOfSpaceError “The image library could not be saved.” “The volume Macintosh HD is out of space.” NSLocalizedRecoveryOptionsErrorKey NSRecoveryAttempterErrorKey

Slide 21

Slide 21 text

Localized Description • Beschreibung aus dem Inhalt des Errors • “The image library could not be saved. The volume Macintosh HD is out of space.” • Mehrere Regeln, je nachdem, welche Informationen gesetzt sind. • Dokumentation nur in den Foundation Release Notes: 
 https://developer.apple.com/library/archive/releasenotes/Foundation/RN-Foundation/index.html

Slide 22

Slide 22 text

Responder Chain UIResponder UIView UIApplication UIViewController

Slide 23

Slide 23 text

UIView UIApplication UIViewController Superview UIViewController

Slide 24

Slide 24 text

UIResponder erweitern @interface UIResponder (STIErrorPresentation) - (void)presentError:(NSError *)error completionHandler:(nullable void (^)(BOOL didRecover))completionHandler; - (nullable NSError *)willPresentError:(NSError *)error; @end

Slide 25

Slide 25 text

UIApplication UIViewController UIViewController AppDelegate willPresentError: willPresentError: willPresentError: willPresentError: presentError: presentError: presentError: presentError: Achtung: Niemals [UIResponder presentError:] überschreiben

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Erneut versuchen

Slide 28

Slide 28 text

NSError Code Domain NSLocalizedDescriptionKey NSLocalizedFailureErrorKey NSLocalizedFailureReasonErrorKey NSLocalizedRecoverySuggestionErrorKey … Beispiel: NSFileWriteOutOfSpaceError “The image library could not be saved.” “The volume Macintosh HD is out of space.” NSLocalizedRecoveryOptionsErrorKey NSRecoveryAttempterErrorKey

Slide 29

Slide 29 text

@interface NSObject(NSErrorRecoveryAttempting) - (BOOL)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex; @end

Slide 30

Slide 30 text

STIRecoveryAttempter *a = [STIRecoveryAttempter new]; [a addOkayRecoveryOption]; [a addRecoveryOptionWithTitle: @"Retry" recoveryAttempt:^BOOL{ return YES; }]; NSError *_error = [error addingObject:a forUserInfoKey:NSRecoveryAttempterErrorKey]; [self presentError:_error completionHandler:^(BOOL didRecover) { if (didRecover) { [self loadFlightStatusUsingFlightnumber]; } }];

Slide 31

Slide 31 text

Problem • Error Fall wird komplizierter • Duplizierter Code • Retry Option wird an jeden Error angehangen • Besser: Konfiguriere Errors an zentraler Stelle!

Slide 32

Slide 32 text

UIApplication UIViewController UIViewController AppDelegate willPresentError: willPresentError: willPresentError: willPresentError: presentError: presentError: presentError: presentError:

Slide 33

Slide 33 text

UIApplication UIViewController UIViewController AppDelegate willPresentError: willPresentError: willPresentError: willPresentError:

Slide 34

Slide 34 text

UIApplication UIViewController UIViewController willPresentError: willPresentError: willPresentError: STIErrorConfigurator willPresentError: STIErrorConfigurator STIErrorConfigurator NSError -domain -code

Slide 35

Slide 35 text

UIApplication UIViewController UIViewController willPresentError: willPresentError: willPresentError: STIErrorConfigurator willPresentError: STIErrorConfigurator STIErrorConfigurator NSError -domain -code Recovery Attempter

Slide 36

Slide 36 text

UIApplication UIViewController UIViewController willPresentError: willPresentError: willPresentError: STIErrorConfigurator willPresentError: STIErrorConfigurator STIErrorConfigurator NSError -domain -code Recovery Attempter

Slide 37

Slide 37 text

UIApplication UIViewController UIViewController willPresentError: willPresentError: willPresentError: STIErrorConfigurator willPresentError: STIErrorConfigurator STIErrorConfigurator NSError -domain -code Recovery Attempter

Slide 38

Slide 38 text

Abfangen

Slide 39

Slide 39 text

@interface UIResponder (STIErrorPresentation) - (BOOL)canInterceptError:(NSError *)error; - (void)interceptError:(NSError *)error completionHandler:(void (^)(BOOL didRecover))completionHandler; @end Error Domains nutzen

Slide 40

Slide 40 text

STIErrorHandling • Open Source • Fork von HRSCustomErrorHandling • Schlank • Optimal auch für kleine Projekte • https://github.com/iCarambaa/STIErrorHandling

Slide 41

Slide 41 text

Demo

Slide 42

Slide 42 text

Zusammenfassung • Jeder Error der auftreten kann, tritt auch auf • Informationen aus NSError nutzen • Responder Chain kann den Fluss übernehmen • Besonders in kleinen Projekten eine einfache Lösung

Slide 43

Slide 43 text

Q&A • Error erstellen • Responder Chain • Error-Präsentation • Error Configurator @s_titgemeyer • STIErrorHandling • Swift