Swiftの匿名関数

この出版物は、2015年のO'ReillyのMatt Neuburg による素晴らしい本「iOS 8 Programming Fundamentals with Swift」の関連セクションの概要です。匿名関数の使用について説明している記事は、初心者にとって興味深いか、より高度な開発者のためのチートシートとして役立ちます



例を考えてみましょう:



func whatToAnimate() {//self.myButton     Self.myButton.frame.origin.y += 20 } func whatToDoLater(finished:Bool) { printLn(“finished: \(finished)”) } UIView.animateWithDuration( 0.4, animations: whatToAnimate, completion: whatToDoLater)
      
      





このセクションのコードには奇妙な点があります。 whatToAnimateおよびwhatToDoLater関数は、これらの関数を次のコード行に渡すためだけに宣言します。 実際、これらの関数の名前はもう必要ありません。名前も関数も再利用されません。 これらの関数の名前のみを宣言せずに、これらの関数の本体のみを転送することをお勧めします。



このような関数は匿名と呼ばれ、存在する権利があり、Swiftでよく使用されます。



無名関数を作成する



無名関数を作成するには、2つのことを行います。

  1. 周囲の中括弧を含む関数の本体を作成しますが、関数の宣言は行いません。
  2. 必要に応じて、中括弧内の最初の行で、inコマンドの後、関数の引数のリストと返される変数の型を記述します。


関数を匿名に変換する方法の例を見てみましょう。 ソース関数コード:



  func whatToAnimate () { Self.mybutton.frame.origin.y += 20 }
      
      





同じタスクを実行する匿名関数の例を次に示します。 引数リストと戻り値の型を中括弧内に移動しました:



  { () -> () in self.myButton.frame.origin.y += 20 }
      
      





無名関数の作成方法がわかったので、それを使用する方法を見てみましょう。 animateWithDurationの呼び出しで、関数を呼び出すポイントは、この関数に引数を渡す場所です。 したがって、次のように、同じ時点で匿名関数を作成できます。



  UIView.animateWithDuration(0.4, animations: { () -> () in self.myButton.frame.origin.y += 20 } , completion: { (finished:Bool) -> () in printLn(“finished: \(finished)”) })
      
      





Swiftでは匿名関数が頻繁に使用されるため、このようなコードを簡単に読み書きできるようにする必要があります。 無名関数は非常に一般的で非常に重要であるため、それらを作成するためにいくつかの略語が使用されています。 そのような場合を考慮してください。



返される変数の型を省略します



コンパイラーが関数が返す変数のタイプをすでに知っている場合は、矢印演算子、変数のタイプおよび指定を省略できます。



  UIView.animateWithDuration(0.4, animations: { () in self.myButton.frame.origin.y += 20 }, completion: { (finished:Bool) in printLn(“finished: \(finished)”) })
      
      







引数がない場合、in演算子で行を省略します



無名関数が引数を取らず、返された変数の型を省略できる場合、inコマンドを含む行は完全に省略できます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }, ompletion: { (finished:Bool) in printLn(“finished: \(finished)”) })
      
      







引数の種類を省略する



無名関数が引数を取り、その型がコンパイラーに知られている場合、これらの型は省略できます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }, completion: { (finished) in printLn(“finished: \(finished)”) })
      
      







括弧を省略します



引数のタイプを省略できる場合、これらの引数を囲む括弧は省略できます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }, completion: { finished in printLn(“finished: \(finished)”) })
      
      







引数がある場合でも、inで行を省略します



戻り値の型を省略することができ、引数の型がコンパイラーに知られている場合、inを含む行を省略し、$ 0、$ 1などの名前を順番に使用して、匿名関数の本体から直接引数を参照できます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }, completion: { printLn(“finished: \($0)”) })
      
      







引数名を省略



匿名関数に引数が必要ない場合は、inの行の名前をアンダースコアに置き換えることにより、引数を省略できます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }, completion: { _ in printLn(“finished!”) })
      
      







ご注意 匿名関数が引数を受け入れる場合、とにかくそれらを使用する必要があります。 inを使用して文字列を省略し、$ 0、$ 1などの名前で引数を使用するか、inを使用して文字列を保存し、引数をアンダースコアに置き換えることができますが、inを含む文字列を同時に省略して、引数を使用することはできませんそれらの名前は0ドル、1ドルです。 これを行うと、コードはコンパイルされません。



呼び出し関数の引数名を省略します



匿名関数が呼び出しで渡される最後のパラメーターである場合、最後のパラメーターの括弧で呼び出しを閉じてから、引数名を指定せずに匿名関数の本体を配置できます。 このメソッドは、トレーリング関数と呼ばれます。



  UIView.animateWithDuration(0.4, animations: { self.myButton.frame.origin.y += 20 }) { _ in printLn(“finished!”) })
      
      







呼び出し関数の括弧を省略します



末尾の関数を使用し、呼び出している関数が渡す関数以外のパラメーターを受け入れない場合、呼び出しで空の角かっこを省略することができます。 たとえば、別の関数を宣言して呼び出します。



  func doThis(f: () -> ()) { f() } doThis { //    printLn(“Hello”) }
      
      





これは、関数呼び出しで角かっこを省略できる唯一の状況です。



戻りキーワードを省略する



無名関数の本体が1つのステートメントのみで構成され、このステートメントがキーワードreturnを持つ戻り値で構成される場合、キーワードreturnは省略できます。 言い換えると、関数が値を返すことが予想される状況で、匿名関数の本体が1つのステートメントのみで構成されている場合、Swiftはこのステートメントが値が匿名関数から返される式であることを意味します。



  func sayHello() -> String { returnHello” } func performAndPrint(f: () -> String) { let s = f() printLn(s) } performAndPrint { sayHello() // return sayHello()   performAndPrint }
      
      







実用化



例を考えてみましょう。 変数の配列があり、mapメソッドを使用して呼び出される、2を乗算した同じ値で構成される新しい配列を取得する必要があります。 マップ配列メソッドは、引数を取り、配列要素と同じ型の変数を返す関数を受け取ります。 配列はInt変数で構成されているため、Intパラメーターを受け取ってIntを返す関数をmapメソッドに渡します。 次のような関数全体を書くことができます。



  let arr = [2, 3, 4, 5, 6] func doubleMe(i:Int) -> { return i*2 } let arr2 = arr.map(doubleMe)
      
      





ただし、このアプローチはSwiftの機能を完全には利用していません。 doubleMe関数は他にどこにも必要ないので、匿名になる可能性が非常に高くなります。 返される変数の型はわかっているため、指定する必要はありません。 パラメーターは1つだけで、それを使用しますが、パラメーターを$ 0として参照する場合、inを含む行は必要ありません。 関数の本体は1つのステートメントで構成され、これはreturnなので、returnを省略できます。 また、map関数は他のパラメーターを受け入れないため、角括弧を省略して、匿名関数の直後に名前を指定できます。



  let arr = [2, 3, 4, 5, 6] let arr2 = arr.map {$0*2}
      
      





匿名機能の使用を開始すると、それらが提供する利点を頻繁に利用することに気付くでしょう。 さらに、関数呼び出しと同じ行に匿名関数全体を配置することにより、コードの量を減らすことがよくあります(ただし、コードを損なうことはありません)。



All Articles