Асинхронная функция iOS не в порядке - PullRequest
0 голосов
/ 25 января 2019

Я новичок в асинхронных вещах в swift, и я пытаюсь реализовать простой асинхронный вызов функции.

import UIKit

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    print("start async")
    sleep(5)   // to simulate long work
    let result: Double = 123.456
    completionHandler(result)
}

print("A")

doAsyncStuff() { result in
    print(result)
}

print("B")

Когда я ее выполняю, я получаю

A
start async
123.456
B

Поскольку функция вызывается асинхронно, я бы ожидал получить

A
start async
B
123.456

Где я ошибся?Большое спасибо

Ответы [ 4 ]

0 голосов
/ 25 января 2019

Ваша функция не асинхронная.Каждая строка кода выполняется синхронно (т. Е. Ожидает завершения строки перед выполнением).Таким образом, sleep (5) приостанавливает выполнение в середине функции и print ("B") не вызывается до тех пор, пока функция не вернется.

Вы можете использовать Grand Central Dispatch (GCD) запускать код асинхронно в другом потоке.Вот пример:

import UIKit

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    DispatchQueue.global(qos: .background).async { [weak self] in
        print("start async")
        sleep(5)
        let result: Double = 123.456
        completionHandler(result)
    }
}

print("A")

doAsyncStuff() { result in
    print(result) // This is your completion handler code
}

print("B")
0 голосов
/ 25 января 2019

Осторожно, вы вызываете свою функцию в том же потоке, поэтому она будет синхронной!

Чтобы вызвать его асинхронно, создайте фоновый поток / задачу и вызовите свою функцию из этого фонового потока. Один из способов сделать это:

print("A")
DispatchQueue.global(qos: .background).async {
    //this is a background thread, do in it your async stuff
    doAsyncStuff() { result in
        print(result)
    }
}
print("B")
0 голосов
/ 25 января 2019

Используйте DispatchQueue.main.asyncAfter для асинхронного вызова в swift.Таким образом, ваш код должен выглядеть так:

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    print("start async")
    DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    // your code goes from here
        let result: Double = 123.456
        completionHandler(result)
    }

}
0 голосов
/ 25 января 2019

Проблема в том, что вы вызываете sleep, который является синхронно блокирующей функцией, поэтому вы блокируете основной поток на 5 секунд, и в это время больше ничего не может быть выполнено. Вы должны использовать DispatchQueue.asyncAfter для проверки простых асинхронных вызовов.

Вы также можете знать, что ваша функция не асинхронная, поскольку вы не получили ошибку компилятора за то, что вы не отметили свое закрытие как @escaping, что вам нужно сделать для обработчиков асинхронного завершения.

func doAsyncStuff(completionHandler: @escaping (_ result: Double) -> Void) {
    print("start async")
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        completionHandler(123.456)
    }
}
...