Swiftで補完ハンドラーを使用して関数を作成するにはどうすればよいですか?


116

私はこれにどのように取り組むかについてちょうど興味がありました。関数があり、それが完全に実行されたときに何かが発生したい場合、これを関数に追加するにはどうすればよいですか?ありがとう


2
Youtubeで素晴らしいビデオがあります:google.com/...は
明るい未来

回答:


174

ネットワークからファイルをダウンロードするダウンロード機能があり、ダウンロードタスクが完了したときに通知を受け取るとします。

typealias CompletionHandler = (success:Bool) -> Void

func downloadFileFromURL(url: NSURL,completionHandler: CompletionHandler) {

    // download code.

    let flag = true // true if download succeed,false otherwise

    completionHandler(success: flag)
}

// How to use it.

downloadFileFromURL(NSURL(string: "url_str")!, { (success) -> Void in

    // When download completes,control flow goes here.
    if success {
        // download success
    } else {
        // download fail
    }
})

それが役に立てば幸い。


2
これはうまく機能しますが、好奇心から言えば、どういうわけか関数に完了ハンドラを記述できるかどうか疑問に思っていました。
traw1233

1
こんにちは、Floksです。他の関数からこのCompletionHandlerを呼び出したいので、これをどのように実現しますか?
Himanshu jamnani

目的cの例
Xcodian Solangi

別のクラスで呼び出すと、完了ハンドラーの成功パラメーターが表示されません。
チャンドニー

85

私は答えを理解するのに苦労したので、私のような他の初心者が私と同じ問題を抱えていると思います。

私の解決策は上の答えと同じですが、うまくいけば、初心者や一般的に理解するのが難しい人のために、もう少し明確で理解しやすいでしょう。

完了ハンドラーを使用して関数を作成するには

func yourFunctionName(finished: () -> Void) {

     print("Doing something!")

     finished()

}

関数を使用するには

     override func viewDidLoad() {

          yourFunctionName {

          //do something here after running your function
           print("Tada!!!!")
          }

    }

あなたの出力は

なんかやってる

多田!!!

お役に立てれば!


80

簡単なSwift 4.0の例:

func method(arg: Bool, completion: (Bool) -> ()) {
    print("First line of code executed")
    // do stuff here to determine what you want to "send back".
    // we are just sending the Boolean value that was sent in "back"
    completion(arg)
}

どうやって使うのですか:

method(arg: true, completion: { (success) -> Void in
    print("Second line of code executed")
    if success { // this will be equal to whatever value is set in this method call
          print("true")
    } else {
         print("false")
    }
})

12

この目的でクロージャーを使用できます。以下をお試しください

func loadHealthCareList(completionClosure: (indexes: NSMutableArray)-> ()) {
      //some code here
      completionClosure(indexes: list)
}

ある時点で、以下のようにこの関数を呼び出すことができます。

healthIndexManager.loadHealthCareList { (indexes) -> () in
            print(indexes)
}

クロージャーについて詳しくは、以下のリンクを参照してください。

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html


5

Swift 5.0 +、シンプルでショート

例:

スタイル1

    func methodName(completionBlock: () -> Void)  {

          print("block_Completion")
          completionBlock()
    }

スタイル2

    func methodName(completionBlock: () -> ())  {

        print("block_Completion")
        completionBlock()
    }

使用する:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        methodName {

            print("Doing something after Block_Completion!!")
        }
    }

出力

block_Completion

Block_Completionの後で何かします!!


0

カスタムメイドの完了ハンドラーについて少し混乱しています。あなたの例では:

ネットワークからファイルをダウンロードするダウンロード機能があり、ダウンロードタスクが完了したときに通知を受け取りたいとします。

typealias CompletionHandler = (success:Bool) -> Void

func downloadFileFromURL(url: NSURL,completionHandler: CompletionHandler) {

    // download code.

    let flag = true // true if download succeed,false otherwise

    completionHandler(success: flag)
}

あなたは// download codeまだ非同期に実行されます。なぜコードは、あなたにまっすぐに行かないだろうlet flag = trueし、completion Handler(success: flag)あなたのダウンロードコードが終了されるのを待たずに?


結局、何かが座ってコードが実行されるのを待つ必要があります。それは、非同期の象の巨大な塔ではありません。「非同期で実行」とは、2つのスレッドがあることを意味します。そのうちの1人は座ってタスクが完了するのを待ち、もう1人は続行し、実行しません。完了ハンドラーは、作業を行うスレッドの最後に呼び出されるか、少なくとも呼び出されるようにスケジュールされます。
2016年

0

上記に加えて、後続クロージャーを使用できます。

downloadFileFromURL(NSURL(string: "url_str")!)  { (success) -> Void in

  // When download completes,control flow goes here.
  if success {
      // download success
  } else {
    // download fail
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.