2

Ich möchte benutzerdefinierte Ausdrücke (wie "2 + 2", "5 + 7" oder komplexer) überprüfen. Ich verwende die NSExpression-Klasse, um diese Ausdrücke zu analysieren und zu berechnen. Das ist mein Spielplatzcode:Korrektes Abfangen von NSInvalidArgumentException bei Verwendung von NSExpression

import UIKit 

let string = "2+2" 

var ex:NSExpression? 
do { 
    ex = NSExpression(format: string) 
} 
catch { 
    print("String is not valid expression") 
} 

if let result = ex?.expressionValue(with: nil, context: nil) as! NSNumber? { 
    print("result is \(result)") 
} 

Wenn ich gültigen Ausdruck ("2 + 2") verwende - bekomme ich das Ergebnis. Aber manchmal Benutzer kann falsche Zeichenfolge ("2+" zum Beispiel) zur Verfügung stellen. Mit dieser Zeichenfolge stürzt meine app mit diesem:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "2+ == 1"' 

Ich verstehe nicht, wie ich diese Ausnahme abfangen kann und warum Code oben tut dies nicht. Jetzt benutze ich Objective C-Klasse (mit derselben Logik), diese Methode von meinem SWIFT-Code aufrufen, und in dieser Klasse wirklich kann ich eine solche Ausnahme fangen:

+(NSNumber *)solveExpression:(NSString *)string 
{ 
    id value; 
    @try { 
     NSExpression *ex = [NSExpression expressionWithFormat:string]; 
     value = [ex expressionValueWithObject:nil context:nil]; 
    } 
    @catch (NSException *e) { } 
    return value; 
} 

Dies funktioniert und ich kann richtig Parse-Zustand (nil Mittel erhalten Probleme mit Ausdruck) und Ergebnis (NSNumber), aber ich möchte wirklich verstehen, wie man all diese Dinge richtig und vollständig in Swift macht.

Antwort

2

NSInvalidArgumentException ist kein abfangbarer Fehler im Sinne von Java-Ausnahmen. Apple garantiert nicht, dass sich Ihr Programm in einem korrekten Zustand befindet, wenn Sie diese Ausnahme bemerken, und es besteht die Möglichkeit, dass etwas schief geht.

Sie sollten wahrscheinlich einen anderen Mechanismus verwenden, um zu überprüfen, ob die Zeichenfolge gültig ist, bevor Sie sie an die Methode übergeben. Diese

+0

Vielen Dank. Sieht so aus, als wäre es besser, die Bibliothek mit der Unterstützung der "Validierung der Ausdrücke" zu benutzen, nicht nur mit dem Ausdruck "Lösen der Ausdrücke". Jetzt schaue ich auf https://github.com/davedelong/DDMathParser –

2

ist, was das Buch Verwendung von Swift mit Cocoa und Objective-Chas to say:

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

[Mein fett]

Nachdem abgeschöpft nur die Referenz für NSExpression ich nicht einen einfachen Weg, um das Problem zu sehen. Das obige Zitat empfiehlt, ein bisschen Objective-C-Code dafür zu schreiben. Der einfachste Weg ist wahrscheinlich eine C-Funktion zu erstellen:

Erklärung:

extern NSExpression* _Nullable makeExpression(NSString* format _Nonnull); 

Definition

NSExpression* _Nullable makeExpression(NSString* format _Nonnull) 
{ 
    NSExpression* ret = nil; 
    @try 
    { 
     // create and assign the expression to ret 
    } 
    @catch(NSException* e) 
    { 
     // ignore 
    } 
    return ret; 
} 

Die Funktion gibt nil für Ausdrücke, die fehlerhaft sind.

Sie könnten wahrscheinlich einen NSError** Parameter hinzufügen, der verwendet wird, wenn ein Fehler auftritt. Sie könnten dies wahrscheinlich auch als Methode in einer Kategorie unter NSExpression definieren und dann würde das Rückgabe-Nil für Fehler/NSError-Füllmuster in Swift wahrscheinlich als Swift-Wurfmethode importiert werden.

Ich sollte übrigens sagen, dass eine Objective-C-Ausnahme nicht wirklich garantiert ist, Ihr Programm in einem konsistenten Zustand zu verlassen. Finger gekreuzt ist in diesem Fall in Ordnung.

Verwandte Themen