https://kotlinlang.org logo
#ios
Title
# ios
a

Andreas Jost

11/26/2019, 10:20 AM
Hi guys, I just realized there is a dedicated ios channel. Let me copy-paste my question from kotlin-native: Can anybody help me, how to add a GestureRecognizer to a UIView from Kotlin? I'm trying to achieve the ability to start a function (passed as a lambda), when a View is pressed. Here is what I tried: (ViewContainer is a typealias for UIView, I want to use this in the common presenter of an Android/iOS-Multiplatform project)
Copy code
actual fun ViewContainer.setOnCLickListener(block: () -> Unit) {
    val funRef = StableRef.create(InvokeClickListener(block))

    this.addGestureRecognizer(UITapGestureRecognizer(this, funRef.asCPointer()))
}

class InvokeClickListener(private val block: () -> Unit) : () -> Unit {
    override operator fun invoke() {
        block()
    }
}
I already managed to set the visibility of Views in the common code. If interested I can post code snippets in the multiplatform channel. But this case is harder, because UITapGestureRecognizer wants a selector/COpaquePointer and I can't find a solution. Error: 'NSInvalidArgumentException', reason: '(null): unrecognized selector sent to instance 0x7f9da94c0a00' Thanks in advance!
a

Artyom Degtyarev [JB]

11/26/2019, 11:58 AM
Hello, @Andreas Jost! One cannot just use COpaquePointer as an equivalent of the selector. Please have a look at the `samples/uikit`(https://github.com/JetBrains/kotlin-native/tree/master/samples/uikit). In the example, it adds target to the UIButton instead of initializing UITapGestureRecognizer, but I think the approach can be shared here. Also, I got to mention that whenever it’s possible to share the whole project - it is welcomed here 🙂.
a

Andreas Jost

11/26/2019, 12:08 PM
Hi @Artyom Degtyarev [JB], I stumbled across the same project a few minutes ago, thanks 🙂 This might not be the best solution, but it's my first approach that works:
Copy code
private fun UIView.setOnCLickListenerActual(block: () -> Unit) {
    this.addGestureRecognizer(UITapGestureRecognizer(Target(block), NSSelectorFromString("invokeBlock")))
}

@ExportObjCClass
class Target(private val block: () -> Unit) {
    @ObjCAction
    fun invokeBlock() {
        block()
    }
}
🎉 1
a

Artyom Degtyarev [JB]

11/26/2019, 12:14 PM
Also, maybe you should inherit this
Tagret
from the
NSObject
, please try it if something will go wrong.
a

Andreas Jost

11/26/2019, 12:53 PM
Inheriting Target from NSObject, I can omit the "@ExportObjCClass"-Annotation and it still works! Are there any other pros for inheriting from NSObject?
m

Matthew Kruk

04/15/2022, 8:38 PM
With the two approaches above I am getting this error message on simulator tap:
Copy code
Class _PathPoint is implemented in both
~filepath~/TextInputUI.framework/TextInputUI (0x14acda6b8). One of the two will be used. Which one is undefined.
I've searched the error and I could only find articles calling it logging noise. Any implementation examples of a tapGesture on a UIView would be greatly appreciated :)
For anyone that runs into the same issue, I solved by adding:
Copy code
override fun gestureRecognizer(
    gestureRecognizer: UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer
): Boolean {
    return true
}
34 Views