Параметры «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() } 

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

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

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

Правильный способ решить эту проблему – удалить 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() } 

Многие люди предлагают параметр 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 с пустой строкой, если вы хотите использовать язык по умолчанию, но просто не getQuestionList параметр:

 let list = getQuestionList() // uses the default "NL" language 
 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() 

}

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

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

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

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

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

 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 } 

Swift 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 к параметру и & его аргументу, для чего был создан этот синтаксис.

Давайте будем гением компьютера.