Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: SDWОтветов: 7

Хорошо, я просто обновил 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()
}
  • Как насчет public func getQuestionList(inout language: String) -> NSArray TotoroTotoro 22.03.2016
  • Нет, это не подходящая замена. OP, вероятно, не хочет, чтобы у getQuestion были какие-либо побочные эффекты. BallpointBen 31.03.2016
  • Честно говоря, я понятия не имею, почему они даже рассмотрели возможность удаления этого. Это была одна из функций, сделавших Swift потрясающим! Danny Bravo 05.04.2016
  • Сам никогда не пользовался и не разбираюсь в суете. Mike Taverne 01.09.2016
  • @MikeTaverne (поздний ответ) Рассмотрим следующую функцию: func foo(_ bar: int) { /*use bar*/ bar+=1; foo(bar); }. Это невозможно без параметров var. Вам нужно либо создать отдельную переменную внутри функции и скопировать значение, либо пометить параметр как inout. Первый медленный, второй вызывает неопределенное поведение. Многие алгоритмы используют такую ​​рекурсию. kevin 22.10.2018
  • @kevin Почему бы в вашей функции просто не вызвать foo(bar + 1)? Mike Taverne 22.10.2018

xcodeswiftswift3xcode7

Ответы

Ответ 1 · рейтинг 83 · garanda

Вы пытались назначить новую переменную

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 · рейтинг 104 · Tr0yJ

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

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

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

Ответ 3 · рейтинг 64 · Elijah

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

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 · рейтинг 13 · Tim Vermeulen

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

Я думаю, что ответы @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 · Mustafa Mohammed

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

Параметры входа-выхода

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

Вы пишете параметр 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 во временной константе с именем временная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. Параметры ввода-вывода - это альтернативный способ для функции иметь эффект, выходящий за рамки ее тела функции.

Ответ 7 · webjprgm

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

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
}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы