Запуск обратного вызова в том же потоке, что и вызывающая сторона в iOS - PullRequest
0 голосов
/ 07 января 2020

Я вызываю метод на нативной стороне iOS из Kotlin / Native framework. Метод выполняет свою работу асинхронно и отвечает некоторыми данными в потоке, отличном от того, который был вызван.

Я хочу, чтобы способ ответа также вызывался в том же потоке. Ниже приведен код:

func makePostRestRequest(url: String, body: String) { 

    let thread1 = Thread.current

    let request = NetworkServiceRequest(url: url,
                                        httpMethod: "POST",
                                        bodyJSON: body)
    NetworkService.processRequest(requestModel: request) { [weak self] (response: Any?, requestStatus: RequestStatus) in
        // This is different thread than "thread1". Need the below code to execute on "thread1"
        if requestStatus.result == .fail {
            knResponseCallback.onError(errorResponse: requestStatus.error)
        } else {
            knResponseCallback.onSuccess(response: response)
        }
    }
}

Я пытался решить эту проблему двумя способами.

Одним из них является использование "семафоров". Я просто заблокировал выполнение кода после сетевого вызова, и когда я получил результат обратно в обратном вызове сетевого запроса, я сохранил его в переменной и дал сигнал семафору. После этого я просто вызываю knResponseCallback и использую переменную response для возврата ответа.

Другой способ, который я использовал, - использовать RunLoops. Я получил дескриптор RunL oop .current, запускаю runL oop в режиме и при обратном вызове сетевого запроса, я просто вызываю perform selector on thread with object метод NSObject, который отправляет работу самому потоку.

Проблема с ними обоими заключается в том, что они блокируют вызовы. RunL oop .run и semaphore.wait оба блокируют поток, в котором они вызваны.

Есть ли способ передать некоторую работу на определенный поток из другого потока, не блокируя конкретный нить?

1 Ответ

0 голосов
/ 09 января 2020

Вам необходимо создать очередь для отправки запроса и использовать эту же очередь для обработки ответа. Нечто подобное должно работать у вас:

    let queue = DispatchQueue(label: "my-thread")
        queue.async {
            let request = NetworkServiceRequest(url: url,
                                                httpMethod: "POST",
                                                bodyJSON: body)
            NetworkService.processRequest(requestModel: request) { [weak self] (response: Any?, requestStatus: RequestStatus) in
                queue.async {
                    if requestStatus.result == .fail {
                        knResponseCallback.onError(errorResponse: requestStatus.error)
                    } else {
                        knResponseCallback.onSuccess(response: response)
                    }
                }
            }
        }
...