I ran into a weird issue that took me a long time ...
# kotlin-native
j
I ran into a weird issue that took me a long time to figure out. Apparently, Objective-C fields can be specified
weak
, `unowned`/`unowned(safe)`, or
unowned(unsafe)
. However, these specifications are not propagated into Kotlin in any way which means you can easily end up with memory access errors randomly if you don't save instances of the fields to other variables that you have more control over. Is there any way support for these could be added to the wrappers created by
cinterop
and thus allow us to get warnings to greatly assist in tracking down these random and confusing issues?
g
Good day! Could you please clarify: do you specifically mean objc fields/ivars (which go within braces), objc properties (declared with @property), or something else (since you seem to be using swift’s wording)? Can you maybe provide a code example leading to the issue?
j
You are right that I have essentially no experience with Obj-C. The field I was setting was GLKView.delegate which is marked as such:
Copy code
unowned(unsafe) var delegate: (any GLKViewDelegate)? { get set }
Some example Kotlin code that can generate an issue is:
Copy code
class ViewDelegate: NSObject(), GLKViewDelegateProtocol() {
    val frame = 0
    override fun glkView(view: GLKView, drawInRect: CValue<CGRect>) {
        println("frame: ${frame++}")
    }
}
val view = GLKView()
view.delegate = ViewDelegate()
// some time later... (largest timeout I have seen is 10 seconds)
view.delegate.glkView(view, CGRectMake(0.0, 0.0, 1.0, 1.0))
// that will cause a memory access issue / sigabrt
The solution in this case is to save the ViewDelegate object to some other variable that you can control the lifetime of, but since I never needed to interact with it myself (the
glkView
function was being called automatically) I didn't causing the issues.
g
This is the intended behavior, mandated by ObjC:
unowned
states that hosting view will not manage lifetimes of values you assign to this property. It means that you, as a developer, is responsible of retaining delegate object to make sure it never outlives
GLKView
instance. Unfortunately, there’s nothing kotlin can do here. Note that GLKit is deprecated, while modern apple api’s tend to use
weak
instead, which wouldn’t produce a dangling pointer and will never lead to this issue.
j
I know GLKit is deprecated, but it is the same in MGLKit and various wrappers for ANGLE on iOS (those expose GL interfaces to the Metal graphics engine). Good to know that they switched to using
weak
instead instead of
unowned
. I know that there is nothing that Kotlin can do to prevent the dangling pointer, but can the KLIB/function definitions be annotated with
@ObjCUnowned
,
@ObjCWeak
, or similar? There is probably not much that can be done in the compiler to produce warnings only in the bad situations like XCode does, without a lot of work, but adding these annotations would make it at least possible to pick on it. Maybe a warning into someone opts-in to saying they are using an unowned field.