【问题标题】:Swift tuple to Optional assignmentSwift 元组到可选赋值
【发布时间】:2015-08-24 02:15:25
【问题描述】:

我正在用 Swift 编写一些代码来学习这门语言。这是我的基类:

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

问题出在最后一行:

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

编译器说“无法表达元组转换 (Status:Int, Error:String) 到 (Int?, String?)”

我知道问题在于 self.status 和 self.message 是可选项,并且 parseResponse 不返回可选项(我不希望它返回)。我如何告诉它进行必要的分配和转换以将数据放入实例变量中?

【问题讨论】:

    标签: ios swift tuples optional


    【解决方案1】:

    建议的另一个答案(在更改之前)只是这样做:

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

    我发现这是不安全的。如果在分配时self.statusself.messagenil,它将崩溃。在 Playground 中尝试此测试:

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

    这是另一种方法:

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

    或者,正如@AndriyGordiychuk 发现的那样,它可以在没有Optional 的情况下工作:

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

    这很好奇,但分配函数的结果却不行。


    注意以下实验:

    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
    

    似乎当赋值是分配给元组的元组文字时,Swift 采取了捷径并且不会首先构造元组。相反,它只是分配单个元素。

    所以这个:

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

    相当于:

    i = 3
    s = "hello"
    

    之所以有效,是因为您可以将Int 分配给Int? 变量,并将String 分配给String? 变量。元组分配失败,因为类型需要匹配。

    【讨论】:

    • 你可以分解元组并重建它 (i, s) = (t.0, t.1)
    【解决方案2】:

    你必须这样做(不需要任何选项):

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

    【讨论】:

    • 如果self.statusself.message 当时是nil,你的第一个方法会崩溃。
    • 我已经测试过了。它不会崩溃。为什么会呢?如果您打开它们并分配给期望非零值的东西,它会崩溃。显式展开 nil 本身不会导致崩溃 ;)
    • 看我的回答。如果 self.statusself.messagenil,我的 Playground 测试在 Xcode 6.4 和 7.0 beta 5 中都会崩溃。
    • @vacawama 好的,你是对的。我将函数输出的打印与一切正常的标志混淆了。尽管如此,还有一个更好的替代方案,因为可以省略 Optional() ;)
    • 投票选出你的最新答案。
    猜你喜欢
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 2014-01-08
    • 1970-01-01
    相关资源
    最近更新 更多