Swift nur um zu verhindern, dass NSKeyedUnarchiver.decodeObject abstürzt?
NSKeyedUnarchiver.decodeObject
verursacht einen Absturz /SIGABRT
wenn die original-Klasse unbekannt ist. Die einzige Lösung, die ich gesehen habe, fangen diese Ausgabe stammt aus dem Swift-Frühgeschichte Bedarf mit Objective C (auch pre-datiert Swift 2 ist die Implementierung von guard
, throws
, try
& catch
). Ich konnte herausfinden, das Ziel C-route - aber ich würde es vorziehen, zu verstehen, eine Rasche Lösung wenn möglich.
Zum Beispiel - die Daten wurden codiert mit NSPropertyListFormat.XMLFormat_v1_0
. Der folgende code wird nicht auf unarchiver.decodeObject()
wenn die Klasse von den verschlüsselten Daten ist unbekannt.
//...
let dat = NSData(contentsOfURL: url)!
let unarchiver = NSKeyedUnarchiver(forReadingWithData: dat)
//it will crash after this if the class in the xml file is not known
if let newListCollection = (unarchiver.decodeObject()) as? List {
return newListCollection
} else {
return nil
}
//...
Ich bin auf der Suche nach einem Swift 2 einzige Weg, um zu testen, ob die Daten gültig sind, bevor Sie versuchen .decodeObject
- da .decodeObject
hat keine throws
- was bedeutet, dass try
- catch
scheint nicht eine option in Swift (Methoden ohne throws
können nicht eingewickelt werden, AFAIK). Oder sonst eine alternative Möglichkeit der Decodierung der Daten, die wirft einen Fehler kann ich abfangen, wenn das Dekodieren fehlschlägt. Ich möchte die Benutzer in der Lage sein, um den import einer Datei von iCloud drive oder Dropbox - daher muss es ordnungsgemäß validiert werden. Ich kann nicht davon ausgehen, dass die codierten Daten sicher.
Den NSKeyedUnarchiver
Methoden .unarchiveTopLevelObjectWithData
& .validateValue
beide haben throws
. Gibt es vielleicht einen Weg, dass diese genutzt werden könnten? Ich kann nicht herausfinden, wie Sie selbst beginnen, zu versuchen, zu implementieren validateValue
in diesem Zusammenhang. Ist das auch ein denkbarer Weg? Oder sollte ich suchen, um eine der anderen Methoden für eine Lösung?
Oder kennt jemand ein Alternatives Swift 2 nur die Art der Auseinandersetzung mit diesem Thema? Ich glaube, dass der Schlüssel ich bin interessiert, ist wohl berechtigt $classname
- aber TBH, ich bin aus meiner Tiefe mit Bezug zu versucht, herauszufinden, wie die Umsetzung validateValue
- oder ob sogar das wäre die richtige Strecke durchzuhalten. Ich habe das Gefühl, dass mir etwas fehlt offensichtlich.
EDIT: Hier ist eine Lösung - Dank rintaro ist toll, die Antwort(en) unten
Die erste Antwort das Problem gelöst, für mich - also die Implementierung einer delegate.
Jetzt aber ich habe eine Lösung gebaut, um rintaro zusätzlich bearbeitet Reaktion wie folgt:
//...
let dat = NSData(contentsOfURL: url)!
let unarchiver = NSKeyedUnarchiver(forReadingWithData: dat)
do {
let decodedDataObject = try unarchiver.decodeTopLevelObject()
if let newListCollection = decodedDataObject as? List {
return newListCollection
} else {
return nil
}
}
catch {
return nil
}
//...
InformationsquelleAutor der Frage simons | 2015-10-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn
NSKeyedUnarchiver
trifft auf unbekannte Klassen,unarchiver(_:cannotDecodeObjectOfClassName:originalClasses:)
delegate-Methode wird aufgerufen.So, Sie können implementieren, die die Delegierten so:
Dann:
HINZUGEFÜGT:
Habe ich nicht bemerkt, dass
NSCoder
hatextension
mit mehr swifty Methoden:Können Sie:
InformationsquelleAutor der Antwort rintaro
einen anderen Weg, kann der name der Klasse verwendet für NSCoding. Sie haben einfach zu verwenden:
NSKeyedArchiver.setClassName("List", forClass: List.self
vor dem serialisierenNSKeyedUnarchiver.setClass(List.self, forClassName: "List")
vor Deserialisierendort, wo Sie gebraucht werden.
Sieht aus wie iOS-Erweiterungen Präfix den Namen der Klasse mit der Endung name.
InformationsquelleAutor der Antwort teriiehina
Eigentlich ist es der Grund, das sollten wir sehr tief Graben Angelegenheiten. Es ist möglich, erstellen Sie eine Archiv-Pfad namens xxx.Archiv und entpacken Sie aus dem Pfad(xxx.Archiv), jetzt ist alles ok. Aber wenn ändern Sie die target-Namen, wenn Sie entpacken, der Absturz aufgetreten ist!!! Es ist, weil Archiv und entpacken der verschiedenen Objekte(die Wahrheit ist, dass wir Archiv und entpacken Ziel.obj, nicht nur die obj).
so einfache Möglichkeit ist das löschen der Archiv-Pfad oder nutzen Sie einfach die verschiedenen Archiv-Pfad. Und dann sollten wir uns überlegen, wie vermeiden Sie den crash, try-catch ist unser Helfer erwähnt rintaro.
InformationsquelleAutor der Antwort user7403994