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


120

好的,所以我只是将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()
}

6
怎么样public func getQuestionList(inout language: String) -> NSArray
龙猫龙猫

2
不,这不是合适的替代品。OP可能不希望getQuestion有任何副作用。
BallpointBen

5
老实说,我不知道他们为什么还要考虑删除它。这是让它变得很棒的功能之一!
丹尼·布拉沃

我从来没有使用过它,也不了解大惊小怪。
Mike Taverne

@MikeTaverne(最新回复)请考虑以下功能:func foo(_ bar: int) { /*use bar*/ bar+=1; foo(bar); }。没有var params,这是不可能的。您要么需要在函数内创建一个单独的var并复制值,要么将参数标记为inout。前者很慢,后者会导致不确定的行为。许多算法都像这样使用递归。
凯文

Answers:


82

您是否尝试分配给新的变量

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

11
我不是OP真正想要的东西
硫磺

6
我会像@garana一样理解OP的问题。OP不在他们的问题中使用inout,他们只是在本地更改一个预先存在的变量。
埃里克·艾雅

11
实际上,这是正确的解决方案。请看到这个建议改变雨燕进化问题:github.com/apple/swift-evolution/blob/master/proposals/...
斯科特·汤普森

8
@TimVermeulen每个人都想使用渐进式语言。Apple可以通过多种方式开发其语言,而不必每个月更改语法。如您所知,由于苹果,大量的在线文档和代码段已过期或过时。因此,开发人员必须反复访问此站点,以寻求许多愚蠢问题的帮助。如果苹果希望更多的开发人员精通该语法,那么从一开始就必须具备牢固的语法。
TomSawyer

25
如果您不想引入另一个变量名(这是imo参数首先在imo中的主要优势),请使用var language = language-
哈里斯(Harris

102

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

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

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


44
我完全不了解此更改,为什么要写另一行来创建可变的本地var比仅将param定义为var更好呢?
Ross Barbish

对我而言,此更改很好,因为它正在适应本应实现局部变量的情况,但我却没有这样做,因为我采取了简单的方法并接受了(旧的)Swift关于将输入参数
设为

1
我对此有@RossBarbish。那么...这被删除了,因为懒惰的开发人员无法区分inout和var参数?Pfff ...
Danny Bravo

1
这似乎非常不必要...,他们应该保留两个选项。
奥斯卡·戈麦斯

1
无论如何,可能很快就在幕后声明了局部变量。现在我们必须手动进行。性能没有变化,但是我们失去了使用简单概念帮助初学者的便利。
mogelbuster '17

62

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

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

5
迄今为止最好的答案。只需要更改一行。
Ballpoint

但是看起来很不自然@James
asyncwait '16

1
我觉得这是最好的答案,因为它保持不变。与其他通用语言的用法类似。
eonist

1
@RiverSatya为什么不直接使用该参数?
Declan McKenna

1
真的是一个很棒的建议。我们将在Swiftify中以这种方式实现它:)
Crulex

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

3
我也不明白为什么当OP甚至在一开始都不使用时,每个人都跳进inout解决方案……
Eric Aya

1
他们以为var和inout做同样的事情。
ryantxr 16-3-22

2

斯威夫特4

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

getQuestionList(language: &someString)

在某些情况下,按照我的经验(涉及数组的更复杂的设置),在方法中创建新属性并对该属性进行更改可能并不总是可行。更不用说,您正在使方法混乱,而不是简单地附加inout到参数&及其参数,这正是创建此语法的目的。



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

0

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

输入输出参数

函数参数默认为常量。试图从函数主体中更改函数参数的值会导致编译时错误。这意味着您不能错误地更改参数的值。如果您希望函数修改参数的值,并且希望这些更改在函数调用结束后仍然存在,请将该参数定义为输入输出参数。

您可以通过将inout关键字放在参数类型的前面来编写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的值存储在一个称为临时A的临时常量中,然后将b的值赋给a,然后将临时A赋给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的值。输入输出参数是函数在函数主体范围之外产生影响的另一种方法。


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
}

我的答案是,如果您希望由调用方看到的原始值将被修改。如果您只是希望能够在本地重新分配值,但又不影响调用者,则可以使用上面的其他答案。
webjprgm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.