it-swarm.com.de

Swift 2: Call kann werfen, aber es ist nicht mit 'try' markiert und der Fehler wird nicht behandelt

Nachdem ich Xcode 7 Beta installiert und meinen Code Swift= in Swift 2) konvertiert habe, habe ich ein Problem mit dem Code, das ich nicht herausfinden kann. Ich weiß Swift 2 ist neu, also suche ich und finde es heraus, da es nichts darüber gibt, sollte ich eine Frage schreiben.

Hier ist der Fehler:

Call kann werfen, ist aber nicht mit 'try' markiert und der Fehler wird nicht behandelt

Code:

func deleteAccountDetail(){
        let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
        let request = NSFetchRequest()
        request.entity = entityDescription

        //The Line Below is where i expect the error
        let fetchedEntities = self.Context!.executeFetchRequest(request) as! [AccountDetail]

        for entity in fetchedEntities {
        self.Context!.deleteObject(entity)
        }

        do {
            try self.Context!.save()
        } catch _ {
        }

    }

Schnappschuss: enter image description here

147
Farhad

Sie müssen den Fehler abfangen, wie Sie es bereits für Ihren save() -Aufruf getan haben, und da Sie hier mehrere Fehler behandeln, können Sie try mehrere Aufrufe nacheinander in einem einzigen do-catch ausführen blockieren, wie so:

func deleteAccountDetail() {
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
    let request = NSFetchRequest()
    request.entity = entityDescription

    do {
        let fetchedEntities = try self.Context!.executeFetchRequest(request) as! [AccountDetail]

        for entity in fetchedEntities {
            self.Context!.deleteObject(entity)
        }

        try self.Context!.save()
    } catch {
        print(error)
    }
}

Wie in den Kommentaren unten unter @ bames53 erwähnt, ist es häufig besser, den Fehler nicht dort abzufangen, wo er ausgelöst wurde. Sie können die Methode als throws und dann als try markieren, um die Methode aufzurufen. Zum Beispiel:

func deleteAccountDetail() throws {
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
    let request = NSFetchRequest()

    request.entity = entityDescription

    let fetchedEntities = try Context.executeFetchRequest(request) as! [AccountDetail]

    for entity in fetchedEntities {
        self.Context!.deleteObject(entity)
    }

    try self.Context!.save()
}
155
Mick MacCallum

Wenn Sie eine Funktion aufrufen, die in Swift mit throws deklariert ist, müssen Sie die Funktionsaufrufsite mit try oder try! Kommentieren. Zum Beispiel, wenn eine Wurffunktion gegeben ist:

func willOnlyThrowIfTrue(value: Bool) throws {
  if value { throw someError }
}

diese Funktion kann wie folgt aufgerufen werden:

func foo(value: Bool) throws {
  try willOnlyThrowIfTrue(value)
}

Hier kommentieren wir den Aufruf mit try, wodurch der Leser darauf hingewiesen wird, dass diese Funktion möglicherweise eine Ausnahme auslöst und die folgenden Codezeilen möglicherweise nicht ausgeführt werden. Wir müssen diese Funktion auch mit throws kommentieren, da diese Funktion eine Ausnahme auslösen kann (d. H. Wenn willOnlyThrowIfTrue() auslöst, wirft foo die Ausnahme automatisch nach oben.

Wenn Sie eine Funktion aufrufen möchten, die als möglicherweise auslösend deklariert ist, von der Sie jedoch wissen, dass sie in Ihrem Fall nicht ausgelöst wird, weil Sie die richtige Eingabe vornehmen, können Sie try! Verwenden.

func bar() {
  try! willOnlyThrowIfTrue(false)
}

Auf diese Weise müssen Sie keinen zusätzlichen Code eingeben, um die Weitergabe von Ausnahmen zu deaktivieren, wenn Sie sicherstellen, dass der Code nicht ausgelöst wird.

try! Wird zur Laufzeit erzwungen: Wenn Sie try! Verwenden und die Funktion am Ende ausgelöst wird, wird die Ausführung Ihres Programms mit einem Laufzeitfehler beendet.

Die meisten Ausnahmebehandlungscodes sollten wie folgt aussehen: Entweder geben Sie Ausnahmen einfach nach oben weiter, wenn sie auftreten, oder Sie richten Bedingungen so ein, dass ansonsten mögliche Ausnahmen ausgeschlossen werden. Jegliche Bereinigung anderer Ressourcen in Ihrem Code sollte über Objektzerstörung (d. H. deinit()) oder manchmal über defered-Code erfolgen.

func baz(value: Bool) throws {

  var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
  var data = NSData(contentsOfFile:filePath)

  try willOnlyThrowIfTrue(value)

  // data and filePath automatically cleaned up, even when an exception occurs.
}

Wenn Sie aus irgendeinem Grund Bereinigungscode haben, der ausgeführt werden muss, sich jedoch nicht in einer deinit() -Funktion befindet, können Sie defer verwenden.

func qux(value: Bool) throws {
  defer {
    print("this code runs when the function exits, even when it exits by an exception")
  }

  try willOnlyThrowIfTrue(value)
}

Der meiste Code, der sich mit Ausnahmen befasst, lässt sie einfach nach oben an die Aufrufer weiterleiten und bereinigt sie unterwegs über deinit() oder defer. Dies liegt daran, dass die meisten Codes nicht wissen, wie sie mit Fehlern umgehen sollen. Es weiß, was schief gelaufen ist, aber es verfügt nicht über genügend Informationen darüber, was ein Code höherer Ebene versucht, um zu wissen, was gegen den Fehler zu tun ist. Es weiß nicht, ob es angebracht ist, dem Benutzer einen Dialog vorzulegen, ob es erneut versucht werden sollte oder ob etwas anderes angebracht ist.

Code auf höherer Ebene sollte jedoch genau wissen, was im Falle eines Fehlers zu tun ist. Ausnahmen ermöglichen es also, dass bestimmte Fehler von der Stelle, an der sie anfänglich auftreten, zu der Stelle, an der sie behandelt werden können, aufsprudeln.

Die Behandlung von Ausnahmen erfolgt über catch -Anweisungen.

func quux(value: Bool) {
  do {
    try willOnlyThrowIfTrue(value)
  } catch {
    // handle error
  }
}

Sie können mehrere catch-Anweisungen haben, von denen jede eine andere Art von Ausnahme abfängt.

  do {
    try someFunctionThatThowsDifferentExceptions()
  } catch MyErrorType.errorA {
    // handle errorA
  } catch MyErrorType.errorB {
    // handle errorB
  } catch {
    // handle other errors
  }

Weitere Informationen zu Best Practices mit Ausnahmen finden Sie unter http://exceptionsafecode.com/ . Es richtet sich speziell an C++, aber nach der Untersuchung des Swift Ausnahmemodells glaube ich, dass die Grundlagen auch für Swift gelten.

Einzelheiten zum Syntax- und Fehlerbehandlungsmodell von Swift) finden Sie im Buch The Swift Programming Language ( Swift 2 Prerelease) .

39
bames53