Hi, is there a way to try/catch an `IncorrectDeref...
# kotlin-native
s
Hi, is there a way to try/catch an
IncorrectDereferenceException
? I want to use the iOS CMAltimeter class, but it's callback gets called from a non-main-thread when
altimeter?.stopRelativeAltitudeUpdates()
is called. I tried a surrounding
try
and
catch
, but no luck. I can not freeze the callback, because that would freeze
update()
too. I really don't know what else to do right now.
Copy code
altimeter = CMAltimeter()
            altimeter?.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue) { data: CMAltitudeData?, error: NSError? ->
                update(data.pressure.doubleValue)
            }
Can the relaxed mode help? If so, how to enable it?
k
given the K/N memory model, you might want to think about this in terms of defining an interface in Kotlin and passing the implementation from swift/Obj-C
k
You just need to make sure you’re back in the main thread. Schedule a call with GCD to main thread, and only access the callback there. Will dig up some code in a bit.
s
@kpgalligan Hi Kevin, thanks for the message! Sorry, but that does not work. It's the access to the CMAltimeter's callback that crashes, not the call to
update(data.pressure.doubleValue)
@Kris Wong Arg, i was hoping there was an 'easy' fix. Thanks for the message! I'll try that
k
There is (probably) an easy fix. I’m in a meeting. Will get back to you later.
OK. Not “easy” if you’re unfamiliar with KN threads, but we’ve built some libraries around this stuff. The point is to ensure the non-frozen data stays in the thread is came from. I’m only seeing a small snippet and not running the code, so I can’t tell you if this will do what you need it to do
Copy code
@ThreadLocal
object Altimeter{
    val altimeter = CMAltimeter()

    fun startUpdates() {
        if(!isMainThread)
            throw java.lang.IllegalStateException("Nah")
        
        val callback = StableRef.create({ data: CMAltitudeData ->
            update(data.pressure.doubleValue)
        })

        altimeter?.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue) { data: CMAltitudeData?, error: NSError? ->
            if(data != null && isMainThread){
                callback.get().invoke(data)
            }
        }.freeze()
    }

    fun update(){
        //???
    }
}
These’s other stuff you need to worry about. Dispose the StableRef, what do you do on that last call that’s not on the main thread, etc.
k
that is some ugliness right there 😛
k
Maybe. I’d say not knowing (or caring) what thread you’re coming back on isn’t pretty either. You can simplify the code some with less explicit checking and/or scheduling all callbacks on a known thread (which you should probably do anyway, assuming
update
is manipulating something that should only be touched in main thread).
Copy code
fun startUpdates() {
        val callback = StableRef.create({ data: CMAltitudeData ->
            update(data.pressure.doubleValue)
        })

        altimeter?.startRelativeAltitudeUpdatesToQueue() { data: CMAltitudeData?, error: NSError? ->
            inMainThread{
                callback.get().invoke(data!!)
            }
        }.freeze()
    }
Well, you’ll need to freeze the data too and make sure it’s safe.
s
@olonho Thank you very much! that mainContinuation is quite nice and works well.