さて、Xcodeを7.3にアップデートするだけで、次の警告が表示されます。
'var'パラメータは非推奨であり、Swift 3で削除されます
この関数で変数を使用する必要があるときにこれを修正する方法:
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(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
変数を導入することです。ルーチンの上部で、パラメーターの値をその変数にコピーします。
関数の先頭に次の1行を追加するだけです。
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
を呼び出さないようにしてください。ただし、パラメータは省略します。
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()
}
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
をパラメーターに追加し、&
を引数に追加するのではなく、この構文が作成されたメソッドが散らかっています。
@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()
}
入出力パラメーター
関数パラメーターはデフォルトでは定数です。関数の本体内から関数パラメーターの値を変更しようとすると、コンパイル時エラーが発生します。つまり、誤ってパラメーターの値を変更することはできません。関数でパラメーターの値を変更し、関数の呼び出しが終了した後もこれらの変更を保持する場合は、代わりにそのパラメーターを入出力パラメーターとして定義します。
パラメータのタイプの直前にinoutキーワードを配置して、in-outパラメータを記述します。 in-outパラメーターには、関数に渡される値があり、関数によって変更され、元の値を置き換えるために関数から戻されます。 in-outパラメーターの動作と関連するコンパイラーの最適化の詳細については、in-outパラメーターを参照してください。
In-outパラメーターの引数としてのみ変数を渡すことができます。定数とリテラルは変更できないため、定数またはリテラル値を引数として渡すことはできません。変数をin-outパラメーターに引数として渡すとき、変数名の直前にアンパーサンド(&)を配置して、関数によって変更できることを示します。
注意
入出力パラメータにデフォルト値を設定したり、可変パラメータを入出力としてマークしたりすることはできません。
次に、swapTwoInts(::)という関数の例を示します。この関数には、aおよびbという2つのin-out整数パラメーターがあります。
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に割り当てることにより、このスワップを実行します。
SwapTwoInts(::)関数をInt型の2つの変数で呼び出して、値を交換できます。 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パラメーターは、関数が関数本体の範囲外で効果を発揮するための代替方法です。
別のアイデアがあります。私のユースケースは、追加する文字列配列を渡すことでした。そのためには、配列を変更可能に渡す必要があります。これについてもクラスに状態を持ちたくありませんでした。そこで、配列を保持するクラスを作成して渡します。ユースケースによっては、その1つの変数だけを保持するクラスがあるのはばかげているように見えるかもしれません。
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
}