Параметры "var" устарели и будут удалены в Swift 3

Хорошо, поэтому я просто обновляю 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()
}

Ответ 1

Вы пытались назначить новый 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()
}

Ответ 2

Обсуждение удаления Var из параметра функции полностью задокументировано в этом представлении на GitHub: Удалить параметры Var

В этом документе вы обнаружите, что люди часто путают параметры var с параметрами inout. Параметр var просто означает, что параметр изменен в контексте функции, а с параметром inout значение параметра в точке возврата будет скопировано вне функции и в контексте вызывающего абонента.

Правильный способ решить эту проблему - удалить var из параметра и ввести локальную переменную var. В верхней части рутины скопируйте значение параметра в эту переменную.

Ответ 3

Просто добавьте эту строку в начале функции:

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

Ответ 4

Многие люди предлагают параметр 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

Ответ 5

Я думаю, что ответы @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()
}

Ответ 6

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

Параметры In-Out

Функциональные параметры по умолчанию являются константами. Попытка изменить значение параметра функции из тела этой функции приводит к ошибке времени компиляции. Это означает, что вы не можете изменить значение параметра по ошибке. Если вы хотите, чтобы функция изменяла значение параметра, и вы хотите, чтобы эти изменения сохранялись после завершения вызова функции, определите этот параметр как параметр in-out.

Вы записываете входной параметр, помещая ключевое слово inout прямо перед типом параметров. Параметр in-out имеет значение, которое передается функции, изменяется функцией и возвращается из функции для замены исходного значения. Подробное обсуждение поведения параметров in-out и связанных с ними оптимизаций компилятора см. В параметрах In-Out.

Вы можете передавать только переменную в качестве аргумента для параметра in-out. Вы не можете передать в качестве аргумента значение константы или буква, потому что константы и литералы не могут быть изменены. Вы помещаете амперсанд (&) непосредственно перед именем переменных, когда передаете его в качестве аргумента в параметр in-out, чтобы указать, что он может быть изменен функцией.

Примечание

Параметры вывода не могут иметь значения по умолчанию, а переменные параметры не могут быть помечены как inout.

Вот пример функции swapTwoInts (::), которая имеет два внутренних целых параметра a и b:

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

Функция swapTwoInts (::) просто меняет значение b на a и значение a на b. Функция выполняет этот обмен, сохраняя значение a во временной константе, называемой временным А, присваивая значение b a, а затем назначая временным А на b.

Вы можете вызвать функцию swapTwoInts (::) с двумя переменными типа Int для обмена их значениями. Обратите внимание, что имена 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. Параметры in-out являются альтернативным способом для функции, которая имеет эффект вне области действия ее тела функции.

Ответ 7

Вот еще одна идея. Моим вариантом использования было передать массив строк для добавления к нему, для которого массив должен быть передан с изменчиво. Я тоже не хотел иметь состояние в своем классе. Поэтому я создал класс, содержащий массив и передающий его. В зависимости от вашего варианта использования может показаться глупым класс, содержащий только одну переменную.

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

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

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

Я использую только методы append и joined в массиве, поэтому было легко изменить тип с минимальными другими изменениями в моем коде.

Пример использования примера:

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
}