skip to Main Content

I’m trying to get more familiar with KMP (Kotlin Multiplatform)
so I’m trying to call an old API from iOS in kotlin in the iOS module

fun shareText(text: String, subject: String) {
        val activityController = UIActivityViewController(
            activityItems = listOf(text),
            applicationActivities = null,
        )
        val window = UIApplication.sharedApplication.windows().first() as UIWindow?
        activityController.popoverPresentationController()?.sourceView =
            window
        activityController.setTitle(subject)
        window?.rootViewController?.presentViewController(
            activityController as UIViewController,
            animated = true,
            completion = null,
        )
    }

And the implementation seems to be working

Simulator image

However as soon I close the sheet dialog I get message in the log

[ShareSheet] connection invalidated

Why some properties names different in kotlin than swift??

the code

UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true, completion: nil)

is

(UIApplication.sharedApplication.windows().first() as UIWindow?)?.rootViewController?.presentViewController(
            activityController as UIViewController,
            animated = true,
            completion = null,
        )

We still can’t call swift code in our project from Kotlin directly

the way I did it seems to be unsafe, is there a better way to do this??

Thank you for your efforts.

2

Answers


  1. The message in the log is discussed in this post, with no reliable solution to fix it. I see the same message when I present an activity view controller in Swift too. I think you shouldn’t worry about it. It kind of makes sense to log "connection invalidated" when the activity view controller is dismissed, since you just "disconnected" from the process that is running the activity view controller.

    That said, you shouldn’t try to get the window and present the activity view controller from the rootViewController. This might not work if e.g. a sheet is already presented. You would end up trying to present a new view controller from a view controller that is already presenting the sheet, which doesn’t work. Also, the windows property itself is deprecated in iOS 15.

    You should allow the caller to specify the view controller from which the activity view controller is presented, and its popover’s sourceView:

    fun shareText(text: String, subject: String, vc: UIViewController, sourceView: UIView) {
         val activityController = UIActivityViewController(
             activityItems = listOf(text),
             applicationActivities = null,
         )
         activityController.popoverPresentationController()?.sourceView = sourceView
         activityController.setTitle(subject)
         vc.presentViewController(
             activityController as UIViewController,
             animated = true,
             completion = null,
        )
    }
    

    As for the differences from the Swift code, this is because Kotlin looks at the Objective-C names when importing the API to Kotlin.

    In Objective-C, shared is indeed called sharedApplication, and present is called presentViewController.

    The cast activityController as UViewController shouldn’t be necessary as far as I can see, but the cast to UIWindow is needed, because Kotlin imports windows as a List<*> for some reason. Alas, supporting Objective-C generics is tricky.

    Login or Signup to reply.
  2. sharing text using UIActivityViewController in Swift. using Swift code in a Kotlin context, which won’t work as-is. Here’s the equivalent code for sharing text in iOS using UIActivityViewController in Kotlin:

            import platform.UIKit.*
    
            fun shareText(text: String, subject: String, viewController: UIViewController) {
                val activityController = UIActivityViewController(
                    activityItems = listOf(text),
                    applicationActivities = null
                )
    
                activityController.popoverPresentationController?.sourceView = viewController.view
                activityController.setTitle(subject)
    
                viewController.presentViewController(activityController, animated = true, completion = null)
            }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search