ฉันจะสร้างฟังก์ชั่นด้วยตัวจัดการเสร็จสิ้นใน Swift ได้อย่างไร


117

ฉันแค่อยากรู้ว่าฉันจะเข้าใกล้สิ่งนี้ได้อย่างไร ถ้าฉันมีฟังก์ชันและฉันต้องการให้บางอย่างเกิดขึ้นเมื่อมันถูกเรียกใช้งานอย่างสมบูรณ์ฉันจะเพิ่มสิ่งนี้ลงในฟังก์ชันได้อย่างไร ขอบคุณ


2
มีวิดีโอที่น่าทึ่งบน Youtube: google.com/…
Bright Future

คำตอบ:


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

เมื่อฉันเรียกมันโดยคลาสอื่นมันไม่ได้หว่านพารามิเตอร์ความสำเร็จของตัวจัดการความสมบูรณ์
Chandni

86

ฉันมีปัญหาในการเข้าใจคำตอบดังนั้นฉันจึงคิดว่าผู้เริ่มต้นคนอื่น ๆ เช่นตัวฉันเองก็อาจมีปัญหาเช่นเดียวกับฉัน

วิธีแก้ปัญหาของฉันเหมือนกับคำตอบด้านบน แต่หวังว่าจะชัดเจนและเข้าใจง่ายขึ้นสำหรับผู้เริ่มต้นหรือผู้ที่มีปัญหาในการทำความเข้าใจโดยทั่วไป

เพื่อสร้างฟังก์ชันด้วยตัวจัดการที่สมบูรณ์

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

     print("Doing something!")

     finished()

}

เพื่อใช้ฟังก์ชัน

     override func viewDidLoad() {

          yourFunctionName {

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

    }

ผลลัพธ์ของคุณจะเป็น

กำลังทำอะไรบางอย่าง

Tada !!!

หวังว่านี่จะช่วยได้!


80

ตัวอย่าง Simple 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)ไม่ต้องรอให้รหัสดาวน์โหลดของคุณเสร็จสิ้น


ในที่สุดมีบางอย่างที่ต้องนั่งรอให้โค้ดทำงานไม่ใช่หอคอยขนาดยักษ์ที่มีช้างอะซิงโครนัสลงไปจนสุด "Ran asynchronously" หมายความว่ามีสองเธรด คนหนึ่งนั่งและรอให้งานเสร็จอีกคนรับและไม่ทำ ตัวจัดการการเสร็จสิ้นจะถูกเรียกหรืออย่างน้อยก็กำหนดเวลาให้ถูกเรียกที่ส่วนท้ายของเธรดที่ทำงาน
Crowman

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.