The above answer is awesome, and it served me pretty well until I needed to override updateConstraints() - which has to call super.updateConstraints(). Without that, I was getting runtime errors, and I found no way how to do that call via the Kotlin <-> Swift interop (and now I'm reasonably sure it's really not possible).
So instead, I gave up on trying to subclass the custom UIView in Swift, and only focused on actually instantiating it from Kotlin/Native (so that it is easy to pass it the data it needs):
class CustomView : UIView {
/* Data we need to use from the Kotlin Code */
lazy var kotlinClass: KotlinClass? = nil
... init etc. ...
override func updateConstraints() {
... my stuff ...
super.updateConstraints()
}
override func draw(_ rect: CGRect) {
... call the kotlinClass' methods as you need ...
}
}
And implemented a factory function to instantiate it:
func customViewFactory(kotlinClass: KotlinClass) -> UIView {
return CustomView(kotlinClass: kotlinClass)
}
Then early during the app startup, I pass this factory function to the Kotlin/Native code like this:
KotlinClass.Companion.shared.setCustomViewFactory(factory: customViewFactory(kotlinClass:))
In the Kotlin part of the project (that is actually compiled before the Swift part), it looks like this:
class KotlinClass {
companion object {
/* To be used where I want to instantiate the custom UIView from the Kotlin code. */
lateinit var customViewFactory: (kotlinClass: KotlinClass) -> UIView
/* To be used early during the startup of the app from the Swift code. */
fun setCustomViewFactory(factory: (kotlinClass: KotlinClass) -> UIView) {
customViewFactory = factory
}
}
When I want to instantiate the custom UIView in the Kotlin code, I just call:
val customView = customViewFactory(this)
And then I can work with this customView as I need in the Kotlin part, even though the Kotlin part is compiled first.
cValue { CGRectZero }
instead ofCGRectMake(.0, .0, .0, .0)
– Poleax