'var' 参数已弃用,将在 Swift 3 中删除

'var' parameters are deprecated and will be removed in Swift 3

好吧,我只是将 Xcode 更新到 7.3,现在我收到了这个警告:

'var' parameters are deprecated and will be removed in Swift 3

当我需要在此函数中使用 var 时如何解决此问题:

public func getQuestionList(var language: String) -> NSArray {
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}

你试过分配给一个新的变量吗

public func getQuestionList(language: String) -> NSArray {
    var lang = language
    if self.data.count > 0 {
        if (lang.isEmpty) {
            lang = "NL"
        }
        return self.data.objectForKey("questionList" + lang) as! NSArray
    }

    return NSArray()
}

很多人建议使用 inout 参数,但这并不是他们设计的目的。此外,它不允许使用 let 常量或字符串文字调用函数。为什么不简单地在函数签名中添加默认值?

public func getQuestionList(language language: String = "NL") -> NSArray {
    if data.count > 0 {
        return data.objectForKey("questionList" + language) as! NSArray
    } else {
        return NSArray()
    }
}

请确保不要使用空字符串调用 getQuestionList,以防您需要默认语言,而只是省略参数:

let list = getQuestionList() // uses the default "NL" language

有关从函数参数中删除 Var 的讨论在 GitHub 上的提交中有完整记录:Remove Var Parameters

在那篇文档中,您会发现人们经常将 var 参数与 inout 参数混淆。 var 参数仅表示该参数在函数的上下文中是可变的,而对于 inout 参数,return 处的参数值将被复制出函数并进入调用者的上下文。

解决这个问题的正确方法是把参数中的var去掉,引入一个局部的var变量。在例程的顶部,将参数的值复制到该变量中。

只需在函数开头添加这一行:

var language = language

其余代码可以保持不变,如下所示:

public func getQuestionList(language: String) -> NSArray {
    var language = language
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}

我认为@Harris 和@garanda 的回答是最好的方法。

无论如何,在你的情况下,不需要变量,你可以这样做:

public func getQuestionList(language: String) -> NSArray {
    if self.data.count > 0 {
        return self.data.objectForKey("questionList" + (language.isEmpty ? "NL" : language)) as! NSArray
    }
    return NSArray()
}

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html

In-Out 参数

函数参数默认为常量。尝试从函数体内更改函数参数的值会导致 compile-time 错误。这意味着您不能错误地更改参数的值。如果您希望函数修改参数的值,并且希望这些更改在函数调用结束后继续存在,请将该参数定义为 in-out 参数。

您可以通过将 inout 关键字放在参数类型之前来编写 in-out 参数。 in-out 参数有一个值,该值被传入函数,被函数修改,并传回函数外以替换原始值。有关 in-out 参数行为和相关编译器优化的详细讨论,请参阅 In-Out 参数。

您只能将变量作为参数传递给 in-out 参数。您不能将常量或文字值作为参数传递,因为无法修改常量和文字。当您将变量作为实参传递给 in-out 参数时,您可以在变量名称前直接放置一个符号 (&),以指示它可以被函数修改。

注意

In-out参数不能有默认值,可变参数不能标记为inout。

这是一个名为 swapTwoInts(::) 的函数示例,它有两个 in-out 整数参数,分别称为 a 和 b:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

swapTwoInts(::) 函数简单地将 b 的值交换为 a,并将 a 的值交换为 b。该函数通过将 a 的值存储在名为 temporaryA 的临时常量中,将 b 的值赋给 a,然后将 temporaryA 赋给 b。

您可以使用两个 Int 类型的变量调用 swapTwoInts(::) 函数来交换它们的值。请注意,当将 someInt 和 anotherInt 的名称传递给 swapTwoInts(::) 函数时,它们的名称带有一个 & 符号前缀:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"

上面的例子表明 someInt 和 anotherInt 的原始值被 swapTwoInts(::) 函数修改了,即使它们最初是在函数之外定义的。

注意

In-out 参数与 return 函数中的值不同。上面的 swapTwoInts 示例没有定义 return 类型或 return 值,但它仍然修改了 someInt 和 anotherInt 的值。 In-out 参数是函数在其函数体范围之外产生影响的另一种方式。

这是另一个想法。我的用例是传递一个字符串数组以附加到它,为此数组必须可变地传递。为此,我也不想在我的 class 中有状态。所以我做了一个 class 来保存数组并传递它。根据您的用例,拥有一个只包含一个变量的 class 可能看起来很愚蠢。

private class StringBuilder {
    var buffer: [String] = []

    func append(_ str: String) {
        buffer.append(str)
    }

    func toString() -> String {
        return buffer.joined()
    }
}

我只在数组上使用 appendjoined 方法,因此只需对我的代码进行最少的其他更改即可轻松更改类型。

一些示例用法:

private func writeMap(map: LevelMap, url: URL) -> Bool {
    let buffer = StringBuilder()

    if !writeHeader(map: map, buffer: buffer) {
        return false
    }
    if !writeFloors(map: map, buffer: buffer) {
        return false
    }

    let content = buffer.toString()
    do {
        try content.write(to: url, atomically: true, encoding: .utf8)
        return true
    } catch {}
    return false
}

private func writeHeader(map: LevelMap, buffer: StringBuilder) -> Bool {
    buffer.append("something here ...\n")
    return true
}
public func getQuestionList(language: inout String) -> NSArray {
if self.data.count > 0 {
    if (language.isEmpty) {
        language = "NL"
    }
    return self.data.objectForKey("questionList" + language) as! NSArray
}

return NSArray()

}