2016-09-24 1 views
0

Swift 3 ändert, wie NSCoder funktioniert.Swift 3: Wie bekomme ich einen Fehler, wenn die NSCoder decodeX-Funktion einen falschen Werttyp dekodiert?

Wie andere SO Fragen erwähnen, um Werttypen wie Int oder Bool zu dekodieren, müssen Sie eine bestimmte Funktion verwenden. Zum Beispiel wird decodeIntegerInt Werte wie so zu dekodieren verwendet:

let value = decodeInteger(forKey key: TestKey) 

Aber was, wenn der zurückgegebene Wert von decodeInteger ist ein String oder Bool oder etwas anderes als ein Int?

Oder was ist, wenn TestKey tatsächlich auf nichts abbildet, weil es die falschen Schlüsseldaten enthält?

Wie fangen Sie diese Fehler anmutig?

+0

@LeoDabus 0 ist eine gültige Ganzzahl. Wie unterscheiden Sie zwischen einem gültigen und einem ungültigen Fall von 0? – Crashalot

Antwort

4

Die Verwendung von decodeInteger für einen nicht ganzzahligen Schlüssel würde eine Ausnahme auslösen. Leider ist es ein NSException, den Swift nicht direkt behandeln kann (siehe Referenzen unten).

Sie müssen zuerst einen Wrapper schreiben ObjC Ausnahmen in ObjC zu handhaben und es über Swift überbrücken (inspiriert von this answer):

/// ------------------------------------------- 
/// ObjC.h 
/// ------------------------------------------- 
#import <Foundation/Foundation.h> 

@interface ObjC : NSObject 

+ (BOOL)catchException:(void(^)())tryBlock error:(__autoreleasing NSError **)error; 

@end 

/// ------------------------------------------- 
/// ObjC.m 
/// ------------------------------------------- 
#import "ObjC.h" 

@implementation ObjC 

+ (BOOL)catchException:(void(^)())tryBlock error:(__autoreleasing NSError **)error { 
    @try { 
     tryBlock(); 
     return YES; 
    } 
    @catch (NSException *exception) { 
     NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithDictionary:exception.userInfo]; 
     [userInfo setValue:exception.reason forKey:NSLocalizedDescriptionKey]; 
     [userInfo setValue:exception.name forKey:NSUnderlyingErrorKey]; 

     *error = [[NSError alloc] initWithDomain:exception.name 
              code:0 
             userInfo:userInfo]; 
     return NO; 
    } 
} 

@end 

Jetzt können Sie die Ausnahme in Swift fangen:

do { 
    try ObjC.catchException { 
     let age = aDecoder.decodeInteger(forKey: "firstName") 
    } 
} catch { 
    print(error.localizedDescription) 
} 

Referenzen: Using ObjectiveC with Swift: Adopting Cocoa Design Patterns

Obwohl die Swift-Fehlerbehandlung der Ausnahmebehandlung in Objective-C ähnelt, handelt es sich um eine völlig separate Funktion. Wenn eine Objective-C-Methode während der Laufzeit eine Ausnahme auslöst, löst Swift einen Laufzeitfehler aus. Es gibt keine Möglichkeit, direkt in Swift von Objective-C-Ausnahmen zu erholen. Jedes Ausnahmebehandlungsverhalten muss in Objective-C-Code implementiert werden, der von Swift verwendet wird.

+0

Also ist es falsch zu sagen, das ist viel schlimmer als Swift 2, die Sie Fehler wie folgt fangen lassen: 'Wenn Wert = aDecoder.decodeObjectForKey (TestKey) als? Bool { test = Wert } ' – Crashalot

+0

Ich habe keine Xcode 7, um das zu testen, aber wenn es auf Swift 2 funktioniert, dann ja, machte Swift 3 es noch schlimmer. Und das wird nicht die einzige Sache sein, die von Swift 3 schlimmer gemacht wird. Zeiger war ein Schmerz in Swift 2, ein viel größerer Schmerz in Swift 3 –

+0

Was meinst du mit dem Zeigerkommentar? – Crashalot

Verwandte Themen