2016-06-21 14 views
3

Ich habe die folgenden NSDate Extension Initialisierer, um ein NSDate Objekt aus einer gegebenen Zeichenfolge zu erstellen.Failable Initialisierer für Bequemlichkeit init fehlschlägt

extension NSDate { 
    convenience init(string: String) { 
     let dateStringFormatter = NSDateFormatter() 
     dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" 
     let date = dateStringFormatter.dateFromString(string) 

     self.init(timeInterval:0, sinceDate:date!) 
    } 
} 

Aber der Aufruf self.init Methode Kraft auspackt die date Variable, die nicht sicher ist. Also versuche ich dies zu einem fehlgeleiteten Initialisierer zu machen.

extension NSDate { 
    convenience init?(string: String) { 
     let dateStringFormatter = NSDateFormatter() 
     dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" 

     guard let date = dateStringFormatter.dateFromString(string) else { 
      return nil 
     } 

     self.init(timeInterval:0, sinceDate:date) 
    } 
} 

Aber es stürzt mit einem EXC_BAD_ACCESS Fehler bei der nil Rückkehr Linie. Ich kann nicht herausfinden warum.

Was mache ich hier etwas falsch?

+3

Ich weiß, das ist verrückt, aber fügen Sie einen sinnlosen 'self.init' Aufruf innerhalb der Wache (egal was, solange es gelingt). Ich habe Compiler-Fehler gehabt, weil ich mich selbst nicht vollständig eingeweiht habe, selbst wenn ich null zurückgebe. –

+0

@LouFranco Whoa, das hat funktioniert! Ist das ein Swift Bug oder sollen wir das machen? – Isuru

+1

Ich kann das Problem im iOS Simulator nicht reproduzieren, Ihr Code funktioniert gut für mich. –

Antwort

-1

Wenn Sie 10 verwenden, müssen Sie die "superclass" initialisieren, bevor Sie nil zurückgeben. Siehe

convenience init?(string: String) { 
    let dateStringFormatter = NSDateFormatter() 
    dateStringFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" 

    guard let date = dateStringFormatter.dateFromString(string) else { 
     self.init() 
     return nil 
    } 

    self.init(timeInterval:0, sinceDate:date) 
} 

Die docs Staaten

alle von einer gespeicherten Eigenschaften-einschließlich der Klasse aller Eigenschaften die Klasse von seinem erbt Super-muss einen Anfangswert bei der Initialisierung zugewiesen werden.

+0

Das hat sich mit Swift 2.2/Xcode 7.3 geändert. Von https://developer.apple.com/library/prerelease/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc7_release_notes.html: Innerhalb einer Klasse ist ein designierter Initialisierer, der entweder nicht verfügbar ist (init? ()) oder werfen (init() throws) darf vor dem Initialisieren aller gespeicherten Eigenschaften und dem Aufruf von super.init() verlassen werden. Dieses Verhalten macht designierte Initialisierer konsistenter mit Convenience-Initialisierern. ** Convenience-Initialisierer können auch fehlschlagen, bevor eine self.init() - Delegierung ausgeführt wird. ** –

+0

Und ansonsten sollte der Code nicht kompiliert werden und nicht mit einer Laufzeitausnahme abstürzen. –

+0

@MartinR Ich denke nicht, dass das für "Erweiterung/Vererbung" gilt. – Code