125

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

'var' 参数已弃用,将在 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()
}
4

8 回答 8

104

关于从函数参数中删除 Var 的讨论已在 GitHub 上的此提交中完整记录:删除 Var 参数

在该文档中,您会发现人们经常将var参数与inout参数混淆。var参数仅仅意味着参数在函数的上下文中是可变的,而使用参数inout时,返回点的参数值将被复制出函数并进入调用者的上下文。

解决此问题的正确方法是var从参数中删除并引入局部var变量。在例程的顶部,将参数的值复制到该变量中。

于 2016-03-22T21:33:45.093 回答
83

您是否尝试分配给新的 var

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()
}
于 2016-03-22T21:01:49.703 回答
65

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

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()
}
于 2016-03-31T03:02:09.000 回答
13

很多人都在建议一个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
于 2016-03-22T21:13:04.110 回答
1
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()

}

于 2018-01-04T17:51:38.353 回答
0

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

无论如何,在您的情况下,不需要 var,您可以这样做:

public func getQuestionList(language: String) -> NSArray {
    if self.data.count > 0 {
        return self.data.objectForKey("questionList" + (language.isEmpty ? "NL" : language)) as! NSArray
    }
    return NSArray()
}
于 2016-06-14T16:35:37.007 回答
0

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

输入输出参数

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

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

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

笔记

输入输出参数不能有默认值,可变参数不能标记为输入输出。

下面是一个名为 swapTwoInts( : :) 的函数的示例,它有两个称为 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( : :) 函数修改,即使它们最初是在函数外部定义的。

笔记

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

于 2017-01-31T16:03:50.647 回答
0

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

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
}
于 2017-02-12T01:52:21.047 回答