2015-08-24 14 views
11

Tôi đang viết một số mã trong Swift để tìm hiểu ngôn ngữ. Đây là lớp cơ sở của tôi:Tuple nhanh để Phân bổ tùy chọn

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) 
    } 
} 

Vấn đề là trên dòng cuối cùng:

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

Trình biên dịch nói "Không thể diễn tả tuple chuyển đổi (Tình trạng: Int, Lỗi: String) đến (Int ?, Chuỗi?) "

Tôi hiểu rằng vấn đề là self.status và self.message là các tùy chọn và parseResponse không trả lại Optionals (và tôi không muốn nó). Làm thế nào để tôi nói nó để thực hiện việc gán và chuyển đổi cần thiết để lấy dữ liệu vào các biến cá thể?

Trả lời

5

câu trả lời khác đề nghị (trước khi nó được thay đổi) để chỉ làm:

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

Tôi đã tìm thấy rằng là không an toàn. Nó sẽ sụp đổ nếu self.status hoặc self.messagenil tại thời điểm chuyển nhượng. Hãy thử kiểm tra này trong một sân chơi:

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() 

Đây là một cách khác để nó có thể được thực hiện:

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

hoặc, như @AndriyGordiychuk phát hiện, nó hoạt động mà không cần Optional:

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

Thật kỳ lạ khi nó hoạt động, nhưng gán kết quả của hàm đó thì không.


Lưu ý thí nghiệm sau:

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 

Dường như khi chuyển nhượng là một tuple đen gán cho một tuple, Swift có một phím tắt và không đầu tiên xây dựng các tuple. Thay vào đó, chỉ cần gán các phần tử riêng lẻ.

Vì vậy, đây:

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

tương đương với:

i = 3 
s = "hello" 

mà làm việc vì bạn có thể gán một Int một Int? biến và một String cho một biến String?. Việc chuyển tuple thất bại vì các loại cần phải khớp.

+0

bạn có thể phân tách bộ và xây dựng lại nó (i, s) = (t.0, t.1) –

3

Bạn phải làm điều này (không optionals cần thiết):

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

Phương thức đầu tiên của bạn sẽ bị lỗi nếu 'self.status' hoặc' self.message' là 'nil' tại thời điểm đó. – vacawama

+0

Tôi đã thử nghiệm nó. Và nó không sụp đổ. Tại sao nó? Nó sẽ sụp đổ nếu bạn đã unwrapping chúng và gán cho một cái gì đó mà hy vọng giá trị không nil. Rõ ràng unwrapping nil không gây ra một vụ tai nạn của chính nó;) –

+0

Xem câu trả lời của tôi. Kiểm tra sân chơi của tôi bị treo trong cả Xcode 6.4 và 7.0 beta 5 nếu 'self.status' hoặc' self.message' là 'nil'. – vacawama

Các vấn đề liên quan