質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • Swift

    7475questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4211questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

【Swift】クロージャの必要性

解決済

回答 3

投稿

  • 評価
  • クリップ 6
  • VIEW 4,268

engawa

score 23

C言語の勉強が少し行き詰っているので、一時的にSwiftの公式リファレンスを読んでみたのですが、クロージャの概念がよくわかりません。まず定義からしてよくわからないのです。

クロージャ(クロージャー、英語: closure)、関数閉包はプログラミング言語における関数オブジェクトの一種。【Wikiprdia】

いろいろ調べてみたところjavascriptにもこの概念があるようで、メリットは変数の宣言を節約できる云々書いてあったのですが、あまり納得のいく解説がありません。
例えば、以下のようなただの関数と、クロージャを用いたコードがある場合、メリットどころか普通の関数の方が記述量が少ないですよね?(もっと複雑なコードでは重宝するのですかね...)
どなたかクロージャのメリットなど教えていただけませんか。

//関数
func put() {
    print("Hello, world!")
}
put()

//クロージャ
var closure: () -> () = {
    print("Hello, world!")
}
closure()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

確かに挙げられている例は、クロージャーを使う理由がわからないような例ですね、、、

見ているかと思いますが以下参考
やっぱりSwift : 関数 #3 : クロージャ基礎

使っているところを提示したほうが分かりやすいと思いますので、クロージャーを使用した簡単な例を載せます。

処理を呼び出したところにダウンロードした画像が渡ってくる感じなので(コールバック)直感的にコードがかけると思います。

// DownLoadManagerクラスを生成
let api = DownLoadManager()

api.downLoadImage { (image) in

    // ダウンロードした画像を設定
    self.imageView.image = image
}

class DownLoadManager {
    func  downLoadImage(task: (image: UIImage) -> ()) {
        // ダウンロード処理・・・

        // ダウンロードした画像を渡す
        task(image: downLoadImage)
    }
}

実際に動くサンプルは以下になります。
画面表示時に画像をダウンロードしてStoryboardに乗せたUIImageViewに画像を表示しています。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let api = DownLoadManager()
        api.downLoadImage { (image) in

            if let image = image {

                // 画像のダウンロードが成功時画像が設定される
                self.imageView.image = image
            } else {
                print("ダウンロード失敗")
            }
        }
    }
}


class DownLoadManager {

    // クロージャー
    func  downLoadImage(task: (image: UIImage?) -> ()) {

        // 画像ダウンロード
        let url = NSURL(string: "https://teratail.com/uploads/contributed_images/78379419b2c58363c546e3e6e094a8c9.png")
        let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
        let req = NSURLRequest(URL: url!)

        // NSURLSession(通信クラス)のこのメソッドの引数もクロージャー
        let task = session.dataTaskWithRequest(req, completionHandler: { (data, response, error) in

            if let imageData = data , downLoadImage = UIImage(data: imageData) {
                // 画像ダウンロード成功時
                task(image: downLoadImage)

            } else {
                // エラー時
                print("Error!")
                task(image: nil)
            }
        })
        task.resume()
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/11 13:48

    やはり質問に使用したようなコードではなく、より高度な処理で力を発揮するのですね。回答していただいたコードの、メソッドの引数にクロージャを使用しているところなどは、まだ初心者の私には難解でしたが、紹介してくださったリンクの説明を読んで、ふんわりとわかったような気がします。今後リファレンスを読み進め、またこのコードを眺めてみたいと思います。回答ありがとうございました。

    キャンセル

+1

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/11 12:39

    https://teratail.com/questions/32039
    ↑この質問ではjavascriptでiteratorを実装するのにクロージャを使ってますね。

    キャンセル

  • 2016/04/11 13:56

    関数をネストすることがクロージャなのかといったら違うような気もしますが、今の所そのくらいの解釈にとどめておきます。実行時にインクリメントしてくれる関数の例では、クロージャによって値が保持されるという利点があるのですね。なかなか奥が深そうです。回答ありがとうございました。

    キャンセル

0

さくっと言うと、「今定義している変数を、後で使えるのがイイ」というところ。
引数の宣言や、構造体の定義等、いろいろなものを省略できます。
C++ならラムダ式のキャプチャや、関数バインド(std::bind)が似たような機能です。

Swiftの利用経験は少ないので、クロージャ(と呼ばれているあの書き方)について
きっとこの辺りが便利なんだろうなあ、というふんわりと掴んだ感じです。

以下のサイトの解説がとてもわかり易かったです。
http://qiita.com/mochizukikotaro/items/7403835a0dbb00ea71ae

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/11 14:01

    調べた際にこのサイトを読ませていただきました。確かにわかりやすい解説だったのですが、やはりどこかモヤモヤっとしたものがありました。おそらく使用例などのサンプルコードを難しくても読んでみるのがいいのでしょうかね。回答ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7475questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    4211questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。