2015-08-24 6 views
11

Ich schreibe einen Code in Swift, um die Sprache zu lernen. Hier ist meine Basisklasse:Swift Tuple zu Optionale Zuordnung

import Foundation 
class BaseCommand:NSOperation 
{ 
    var status:Int? = nil 
    var message:String? = nil 

    func buildRequest() -> NSData? 
    { 
     return nil 
    } 

    func parseResponse(data:NSData?) -> (Status:Int, Error:String) 
    { 
     return (200, "Success") 
    } 

    override func main() { 
     let requestBody = self.buildRequest() 

     println("Sending body \(requestBody)") 
     // do network op 
     var networkResultBody = "test" 

     var resultBody:NSData = networkResultBody.dataUsingEncoding(NSUTF8StringEncoding)! 
     (self.status, self.message) = self.parseResponse(resultBody) 
    } 
} 

Das Problem in der letzten Zeile ist:

(self.status, self.message) = self.parseResponse(resultBody) 

Der Compiler sagt: „Kann nicht Tupel Umwandlung Express (Stand: Int, Fehler: String) bis (Int ?, String?) "

Ich verstehe, dass das Problem ist, dass self.status und self.message Optionals sind, und die parseResponse Optionals nicht zurückgibt (und ich will es nicht). Wie sage ich es, um die notwendigen Zuweisungen und Konvertierungen durchzuführen, um die Daten in die Instanzvariablen zu bekommen?

Antwort

5

Eine andere Antwort vorgeschlagen (bevor es geändert wurde) nur tun:

(self.status!, self.message!) = self.parseResponse(resultBody) 

ich gefunden habe, das ist unsicher. Es stürzt ab, wenn entweder self.status oder self.message zum Zeitpunkt der Zuweisung nil ist. Versuchen Sie diesen Test in einem Spielplatz:

class Test { 
    var status: Int? 
    var error: String? 

    func parseResponse() -> (Status:Int, Error:String) 
    { 
     return (200, "Success") 
    } 

    func testIt() { 
     (self.status!, self.error!) = parseResponse() 
     print(self.status) 
     print(self.error) 
    } 
} 

let mytest = Test() 
mytest.testIt() 

Hier ist eine andere Art und Weise es getan werden könnte:

let (stat, err) = self.parseResponse(resultBody) 
(self.status, self.error) = (Optional(stat), Optional(err)) 

oder, wie @AndriyGordiychuk entdeckt, funktioniert es ohne Optional:

let (stat, err) = self.parseResponse(resultBody) 
(self.status, self.error) = (stat, err) 

Es ist merkwürdig, dass das funktioniert, aber die Zuweisung des Ergebnisses der Funktion nicht.


Hinweis das folgende Experiment:

var i: Int? 
var s: String? 

// This works 
(i, s) = (3, "hello") 

// This fails with error: cannot express tuple conversion '(Int, String)' to '(Int?, String?) 
let t = (3, "hello") 
(i, s) = t 

Es scheint, dass, wenn die Zuordnung ein Tupel wörtliche zu einem Tupel zugeordnet ist, Swift eine Verknüpfung nimmt und nicht erst in das Tupel konstruieren. Stattdessen werden nur die einzelnen Elemente zugewiesen.

So folgt aus:

(i, s) = (3, "hello") 

entspricht:

i = 3 
s = "hello" 

, die funktioniert, weil Sie eine Int zu einer Int? Variable und eine String zu einer String? Variablen zuweisen können. Die Tupelzuweisung schlägt fehl, da die Typen übereinstimmen müssen.

+0

Sie können Tupel zerlegen und neu aufbauen (i, s) = (t.0, t.1) –

3

Sie haben, dies zu tun (keine Extras erforderlich):

let returnValue = self.parseResponse(resultBody) 
(self.status,self.message) = (returnValue.Status,returnValue.Error) 
+0

Ihre erste Methode stürzt ab, wenn "self.status" oder "self.message" zu der Zeit "null" sind. – vacawama

+0

Ich habe es getestet. Und es stürzt nicht ab. Warum sollte es? Es würde abstürzen, wenn Sie sie auspacken und etwas zuweisen, das Nicht-Null-Werte erwartet. Das explizite Auspacken von nil verursacht selbst keinen Absturz;) –

+0

Siehe meine Antwort. Mein Spielplatztest stürzt sowohl in Xcode 6.4 als auch in 7.0 Beta 5 ab, wenn 'self.status' oder' self.message' 'nil' sind. – vacawama