2016-03-29 10 views
1

Ich habe eine Frage bezüglich der Do/Catch-Syntax, die für AVAudioPlayer benötigt wird. Wofür ist es eigentlich?Ist/catch für AVAudioPlayer unnötig?

Schauen wir uns einige Beispiele an, wie der Code mehr oder weniger nach Tutorials aussehen sollte, die ich gesehen habe.

1) Hier bin ich gezwungen, die optionale NSURL in der try-Anweisung auszupacken. Meine Annahme ist, dass, wenn ich jetzt den mp3-Namen ändere, sollte es den catch-Block aufrufen, stattdessen bekomme ich einen Null-Absturz in der try-Zeile, weil die avPlayerURL-Eigenschaft null ist. Warum wird es nicht gefangen?

do { 
     let avPlayer1URL = NSBundle.mainBundle().URLForResource("Test", withExtension: "mp3") 
     avPlayer1 = try AVAudioPlayer(contentsOfURL: avPlayer1URL!) 
     avPlayer1?.delegate = self 
     avPlayer1?.numberOfLoops = -1 
     avPlayer1?.prepareToPlay() 
    } catch { 
     print("Error finding AVAudioPlayer 1 file") 
    } 

2) Ich zwinge bin die Eigenschaft URL direkt auspacken und das Ergebnis ist das gleiche wie 1. In diesem Fall tho es Sinn macht, weil der Versuch Linie nie aufgerufen. So würde in diesem Beispiel schlechte Codierung sein glaube ich, noch eine Menge Tutorials zeigt es Ihnen auf diese Weise oder Art und Weise 1.

do { 
     let avPlayer1URL = NSBundle.mainBundle().URLForResource("Test", withExtension: "mp3")! 
     avPlayer1 = try AVAudioPlayer(contentsOfURL: avPlayer1URL) 
     avPlayer1?.delegate = self 
     avPlayer1?.numberOfLoops = -1 
     avPlayer1?.prepareToPlay() 
    } catch { 
     print("Error finding AVAudioPlayer 1 file") 
    } 

3) so sicherstellen, dass der NSURL nicht nil ich optional Verkettungs verwenden. Die Sache ist jetzt, dass, wenn es das mp3 nicht finden kann, es den Do-Block überhaupt nicht laufen lässt und deshalb nicht die Versuchlinie oder den Fangblock. Daher wird die gesamte Do/Catch-Sache in diesem Beispiel nicht benötigt.

 do { 
     if let avPlayer1URL = NSBundle.mainBundle().URLForResource("Test", withExtension: "mp3") { 
       avPlayer1 = try AVAudioPlayer(contentsOfURL: avPlayer1URL) 
       avPlayer1?.delegate = self 
       avPlayer1?.numberOfLoops = -1 
       avPlayer1?.prepareToPlay() 
     } 
    } catch { 
     print("Error finding AVAudioPlayer 1 file") 
    } 

Also meine Fragen sind im Grunde

1) Warum ist der Compiler sagt mir, "versuchen" (do/catch)

2) zu verwenden Warum ich einen Absturz am Beispiel bekommen 1

3) Kann der AVAudioPlayer immer noch einen Fehler ausgeben, obwohl ich eine optionale Verkettung verwendet habe, um sicherzustellen, dass der mp3 existiert?

Antwort

3

Ich bekomme einen Nullabsturz in der Try-Zeile, weil die avPlayerURL-Eigenschaft null ist. Warum wird es nicht gefangen?

Swift Fehler mit Do-Fang Handling fängt nur Fehler, ist es nicht Ausnahmen verfängt.

Auspacken a nil Optional führt zu einer Ausnahme, es wird kein Fehler ausgegeben.

Daher wird dieses Problem nicht per Entwurf von catch abgefangen.

Die Verwendung von catch für AVAudioPlayer bedeutet, dass wenn AVAudioPlayer selbst einen Fehler wirft, wird dieser Fehler abgefangen.

Und den Inhalt eines geworfen Fehler angezeigt werden, eine schöne Art und Weise ist die Fehlermeldung zu einem NSError wie folgt niedergeschlagenen:

do { 
    // ... 
} catch let error as NSError { 
    print(error.debugDescription) 
} 

zum Beispiel sagen, Lassen Sie eine MP3-Datei, aber Die Daten dieser Datei sind beschädigt und nicht abspielbar.

Sie werden überprüfen, dass die Datei dort ist wie in Ihrem dritten Beispiel, und es wird die Datei als ok erachten - aber dann der Player wird einen Fehler werfen, weil es nicht in der Lage sein wird, den Inhalt der Datei zu lesen.

+0

Hey, danke für die Antwort. Tut mir leid, aber nur um klarzustellen, wenn ich den sicheren Weg (Beispiel 3) benutze, könnte der AVAudioPlayer immer noch irgendeine Art von Fehler werfen, obwohl ich sichergestellt habe, dass die MP3-Datei existiert? – crashoverride777

+0

Ja, absolut, das sind zwei unabhängige Dinge. Nehmen wir zum Beispiel an, die mp3 ist da, aber ihre Daten sind korrupt. Ihr "wenn avPlayer1URL = NSBundle.mainBundle() ... gelassen wird" wird die Datei in Ordnung finden, aber dann wird der Player einen Fehler ausgeben, weil er den Dateiinhalt nicht lesen kann. – Moritz

+0

Brilliant, darum war ich etwas verwirrt. Könnten Sie vielleicht den Kommentar, den Sie gerade geschrieben haben, in Ihre Antwort schreiben? Vielen Dank – crashoverride777