Paring down my question since it was a bit much co...
# multiplatform
t
Paring down my question since it was a bit much codewise 😅 . I'm struggling with how to deal with this *`Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared kotlinx.coroutines.internal.DispatchedContinuation@2d8048 from other thread` *error. I've copied an implementation of the KaMPKit
NativeViewModel
and have my iOS network implementation done separately in an interface using
URLSession
. Is there anything within the Kotlin/Native concurrency model that makes calling a
URLSession
with a completion handler callback impossible? I'm pretty sure I've done everything I can to make my data state immutable.
Copy code
class SearchViewModel(
    private val repository: SearchRepository,
    private val onSearchState: (SearchState) -> Unit
): KoinComponent {

    private val scope = MainScope(Dispatchers.Main)

    private val _searchStateFlow = MutableStateFlow(SearchState())

    init {
        ensureNeverFrozen()
        observeQueries(_searchStateFlow.value.query)
    }

    @OptIn(FlowPreview::class)
    @Throws(Exception::class)
    fun observeQueries(query: String) {
        _searchStateFlow.value = SearchState(
            query = query,
            isLoading = true)
        scope.launch {
            repository.searchGames(_searchStateFlow.asStateFlow())
                .collect { state ->
                    onSearchState(state)
                }
        }
    }
}
The error happens on the completion handler that is called in the
IOSSearchInteractor
's URLSession callback:
Copy code
class IOSSearchInteractor: SearchInteractor {
    func searchGames(query: String, completion: @escaping (Result<String, Error>) -> Void) {

        var request ...
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            // error happens here on completion handler
            let str = String(decoding: data!, as: UTF8.self)
            completion(.success(str))

        }
        task.resume()
    }
r
If you're using the strict memory model, I think the completion handler needs to be called from the main thread. I'm not sure what thread the dataTask callback runs on. Try wrapping the
completion
call in
DispatchQueue.main.async { }
. Alternatively, consider trying out the new memory model.
k
Agree. It does look like the completion handler itself is the issue, but you would need to do more confirmation. You might need to freeze it regardless, as it being visible to other threads might be problematic, but not sure. Would need to poke around (or use the new memory model).
t
Thanks guys, I actually upgraded the memory model and it works now