This is valid swift code. But doesn't work on Kotlin/Native:

Related issue: https://github.com/JetBrains/kotlin-native/issues/1995
This class is from the platform.AppKit so cannot do the trick of disableDesignatedInitializerChecks
Default initializer here is not designated even in Swift.
Your Swift code snippet is not equivalent to Kotlin one: it doesn't delegate to super.init because it doesn't declare any initializer: by default Swift inherits all initializers from super class.
If you add init() { super.init() } to your Swift class, then you will see that Swift doesn't allow to call super.init() too.
Please delegate to a proper designated initializer, e.g. initWithFrame:.
In the case this helps someone else:

I find it a bit strange. Not sure how swift generates the default init from NSResponder. Maybe because the failable initializers?
Now I somehow understand how it is like that. But I guess other people will have similar issues.
Will try to port code from Swift to K/N that do not provide other initializers, and will stumble upon this problem.
Would be nice if inherited K/N classes from Obj-C/Swift autogenerate proper constructors when no default constructor is provided. Though not sure how complex would be do that. Or at least a quickfix to generate all the constructors automatically, and detect the error at editing time. Specially I'm not sure about how the default init from NSResponder is generated for MyOpenglView, so couldn't reproduce for other classes without manually instantiating the required arguments. Maybe they are providing default values like zero-filled memory for value types? No clue here.
I find it a bit strange. Not sure how swift generates the default
initfromNSResponder.
It is inherited from NSOpenGLView, which inherits it from NSView, which inherits it from NSResponder.
In the case of UIViewController from iOS UIKit, passing a default NSCoder() instance results in a crash, and adding a no-args constructor override results in this same compilation error (that IntelliJ doesn't catch).
Is there a workaround to be able to subclass UIViewController, something very basic for making an iOS app?
Here's an example of a subclass that compiles and can be instantiated if referenced from a storyboard:
@ExportObjCClass
class OldViewController : UIViewController {
@OverrideInit
constructor(coder: NSCoder) : super(coder)
@ObjCOutlet
lateinit var label: UILabel
@ObjCOutlet
lateinit var textField: UITextField
@ObjCOutlet
lateinit var button: UIButton
@ObjCAction
fun buttonPressed() {
label.text = "Konan says: 'Hello, ${textField.text}!'"
}
}
However, if you want to be able to instantiate it from code, breaking free from storyboards, you're out of luck as adding the following results in the compilation error of that issue:
@OverrideInit
constructor() : super()
https://github.com/JetBrains/kotlin-native/issues/2010#issuecomment-418986603
Please delegate to a proper designated initializer, e.g.
initWithFrame:.
@SvyatoslavScherbina How? I don't see how I'd translate that to Kotlin.
I found a way to make my UIViewController subclass usable from Kotlin! There's a third constructor I didn't notice that takes 2 nullable parameters, and passing them null works just fine, and can be set in default parameters from Kotlin! Here's an example snippet:
ExportObjCClass
class MyViewController @OverrideInit constructor(
nibName: String? = null,
bundle: NSBundle? = null
) : UIViewController(nibName, bundle) {
init {
title = "MyViewController"
}
private val button: UIButton = UIButton.buttonWithType(UIButtonTypeSystem).apply {
setTitle("Finally!", UIControlStateNormal)
view.addSubview(this)
setFrame(CGRectMake(x = 10.0, y = 25.0, width = 125.0, height = 75.0))
}
suspend fun run() {
var counter = 0
while (true) {
button.awaitOneClick() // Custom suspending extension function
button.setTitle("Clicked ${++counter} times!", UIControlStateNormal)
}
}
}
Please note that you don't need @ExportObjCClass and @OverrideInit if you instantiate MyViewController manually.
Btw,
init {
title = "MyViewController"
}
How would you do this in Swift without overriding initializers?
That's right, here's a smaller version that works:
private class MyNavViewController : UINavigationController(null, bundle = null) {
// named argument is needed here to disambiguate overload resolution from the navigation UIController
...
}
As for the init block, I think Kotlin wins on that one, Swift doesn't seem to be able to do it without overriding the initializers, although I am not so familiar with it.
Trying to make the same thing using appkit NSViewController to build a desktop app without storyboard but this code lead to a crash
class ViewController : NSViewController(null, bundle = null) { }
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[NSNib _initWithNibNamed:bundle:options:] could not load the nibName: kobjc2 in bundle (null).'
Can't get rid of Unable to call non-designated initializer as super constructor either, and i don't know what to do with disableDesignatedInitializerChecks to try as it's a simple program without any .def file
Any advices would be apreciated :(
i got this error, when i try to inherit IOS WKWebView. Does K/N currently not support this case?
We already discussed @roths question in the Kotlin Slack, so posting it just for the record. One can inherit from WKWebView like this:
import kotlinx.cinterop.*
import platform.WebKit.*
import platform.Foundation.NSZeroRect
class myWebView : WKWebView(frame = NSZeroRect.readValue(), configuration = WKWebViewConfiguration())
@SBNTT: Trying to make the same thing using appkit NSViewController to build a desktop app without storyboard but this code lead to a crash [...]
It's a bit hidden, but here's what it says in the [鈥淒iscussion鈥漖 section of [NSViewController]'s [init(nibName:bundle:)] method reference:
If you pass in
nilfornibNameOrNil, [nibName] returnsniland [loadView()] throws an exception; in this case you must set [view] before [view] is invoked, or override [loadView()].
So, one way to work around the issue is:
import platform.AppKit.NSView
import platform.AppKit.NSViewController
import platform.AppKit.NSWindow
@Suppress("FunctionName")
fun NSViewController(view: NSView) =
object : NSViewController(nibName = null, bundle = null) {
init {
this.view = view
}
}
fun example(view: NSView): NSWindow =
NSWindow.windowWithContentViewController(NSViewController(view))
Most helpful comment
I found a way to make my
UIViewControllersubclass usable from Kotlin! There's a third constructor I didn't notice that takes 2 nullable parameters, and passing them null works just fine, and can be set in default parameters from Kotlin! Here's an example snippet: