Як я можу створити функцію за допомогою обробника завершення в 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
Привіт Флокс, я хочу викликати цей CompletionHandler від іншої функції, як цього досягти ??
Хіманшу джамнані

будь-який приклад для об’єктивного 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

Приклад 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

Швидкий 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)не чекаючи завершення завантаження коду?


Врешті-решт, щось має сидіти і чекати, коли код запуститься, це не велетенська вежа асинхронних слонів аж донизу. "Ран асинхронно" означає, що є дві нитки. Один з них сидить і чекає виконання завдання, інший продовжує і не виконує. Обробник завершення отримує виклик або принаймні запланований виклик в кінці потоку, який виконує роботу.
Crowman

0

На додаток до вищезазначеного: може бути застосовано заднє закриття .

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

  // When download completes,control flow goes here.
  if success {
      // download success
  } else {
    // download fail
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.