kerry
kerry

Reputation: 2582

Running callback on the same thread as the caller in iOS

I call a method on the native iOS side from Kotlin/Native framework. The method does its work asynchronously and responds back with some data in a different thread than it was called with.

I want a way to call the response function also in the same thread. Below is the code:

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)
        }
    }
}

I have tried to solve this using two ways.

One is to use "semaphores". I just blocked the code execution after the network call and when I got the result back in the callback of network request, I saved it in a variable and signal the semaphore. After that I just call knResponseCallback and use the response variable to return back the response.

Another way I used is to use RunLoops. I got the handle of RunLoop.current, start the runLoop in a mode and in the callback of network request, I just call perform selector on thread with object method of NSObject which dispatches the work to that thread itself.

The problem with both of them is that they are blocking calls. RunLoop.run and semaphore.wait both blocks the thread they are called in.

Is there a way to dispatch some work onto a particular thread from another thread without blocking the particular thread?

Upvotes: 1

Views: 530

Answers (1)

aasatt
aasatt

Reputation: 680

You need to create a queue to send the request and use that same queue to handle the response. Something like this should work for you:

    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)
                    }
                }
            }
        }

Upvotes: 0

Related Questions