Hello all, I have a (hopefully not dumb) question...
# compose-ios
l
Hello all, I have a (hopefully not dumb) question. Is there a way to include swiftui view in compose multiplatform (I have Android alternative ready) and allow it to fill its parent container? Any links to some good samples would be appreciated, as I struggle to find something useful in this ever changing library 😅
i
@Dima Avdeev recently added this example check it out
👍 2
l
@Ivan Matkov thanks, this looks promising. Although, that’s for injecting the whole screen view. Can I have somehow the expect-actual for composable that I can use? To further elaborate, I want to display LaTeX text, for which I have a custom AndroidView and SwiftUI views for respective platforms. I want to control where to put it from Compose code, and create a linking for it in swift
i
Although, that’s for injecting the whole screen view.
It's not (see screenshot in readme). Another example of not-full-screen view is mapview in imageviewer example (not swiftUI but anyway).
where to put it from Compose code
Create expect composable function, use
UIKitView
inside actual ios implementation
l
Create expect composable function, use
UIKitView
inside actual ios implementation
Would you mind please elaborate a bit more on this? It’s a bit confusing for me since the example only has iOS part
i
expect/actual function might be
@Composable
, so you can put different UI layout inside. It's not our doc, just some article, but I guess it's ok to ref this as example 😅: https://proandroiddev.com/unifying-video-players-compose-multiplatform-for-ios-android-desktop-aa920d29bbf3
l
Oh, that makes sense. Only one small puzzle piece left, what if I am not using a default UIKit view but have a swiftui library that I imported in XCode and want to reference it in the shared code?
i
Even if you cannot refer it directly from Kotlin for some reason, you always can do it from native/swift part
l
Okay, and how would I do that? Can I create some swift function that I can refer to from the common code?
i
from the common code
You cannot refer it from common. that's why you need expect/actual to refer it only from ios actual implementation
l
yes, that’s what I meant sorry. So, in the “actual” function in iOS platform specific code (still in Compose domain), can I refer to a swift function I defined that will show a SwiftUI content? If so, how?
i
Hm, I see that in our samples only default components are used 🤔 @Dima Avdeev let's add custom view in that samples? Regarding swift library interop: it seems as Kotlin Multiplatform topic, not Compose related. From docs:
A Swift library can be used in Kotlin code if its API is exported to Objective-C with
@objc
. Pure Swift modules are not yet supported.
As far as I know swift support is on the way
l
As far as I know swift support is on the way
Does it mean that for now, it is or it is not possible to do what I need? Basically, this is the library https://github.com/colinc86/LaTeXSwiftUI I want to use in my compose implementation
j
I've got my answer too. I was trying to use GoogleSignIn package but it was not resolving from cocoapods plugin in the gradle
i
To use it from Kotlin/Compose, you can add libraries via CocoaPods: https://kotlinlang.org/docs/native-cocoapods-libraries.html#from-the-cocoapods-repository At the moment, we do not have pre-built examples readily available demonstrating custom components interoperability. Thus, I can only refer to separate components/parts but not the complete puzzle.
l
Yes but that is using cocoapods, I am using swift package manager for this 😕
j
Unfortunately the swift package manager is not yet supported in kotlin native. If supported then we won't face any problem maybe
👍 1
l
Yes, that’s why I had a question if I can: 1. Make a view in swift code 2. Reference it in iOS part of compose 3. use it with expect-actual
j
what i'm doing with lottie is creating an interface in iosMain and implement it in iosApp then return a UIView through interface function and pass it with initializing the implementation class through calling main function from iosApp then you can use it anywhere with LocalComposition. That was very hard way to do that
l
That may be something I need to use, could you please share some code ?
j
Copy code
// in shared/iosMain
interface LottieAnimationInterface {
    fun getView(): UIView

    fun play()
}
Copy code
// in iosApp/LottiAnimationInterface.swift
import Lottie
import UIKit
import shared

class LottieAnimationInterfaceImpl: LottieAnimationInterface{
    private var lottieAnimationView: LottieAnimationView?
    private let animationName:String
    
    init(animationName:String){
        self.animationName = animationName
    }
    
    func getView() -> UIView{
        lottieAnimationView = LottieAnimationView(filePath: self.animationName)
        lottieAnimationView?.loopMode = .loop
        return lottieAnimationView!
    }
    
    func play(){
        lottieAnimationView?.play()
    }
}
Copy code
import UIKit
import SwiftUI
import shared

// This is where you're calling the compose shared code from iosMain and pass the implementation to the shared module
struct ComposeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        MainApp_iosKt.MainViewController(lottieInterfaceFactory: LottieAnimationInterfaceFactoryImpl(), googleLoginInterface: GoogleLoginInterfaceImpl())
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {    }
}
and i'm doing it like this in iosMain module
Copy code
val LocalLottieInterfaceFactory =
    compositionLocalOf<LottieAnimationInterfaceFactory> { DummyLottieInterface() }

fun MainViewController(
    lottieInterfaceFactory: LottieAnimationInterfaceFactory,
    googleLoginInterface: GoogleLoginInterface
): UIViewController {
    val controller = PreComposeApplication {
        CompositionLocalProvider(LocalLottieInterfaceFactory provides lottieInterfaceFactory) {
            KoinApplication(application = {
                modules(
                    module {
                        single { googleLoginInterface }
                    }
                )
                modules(KoinPlatformModule, KoinModule)
            }) {
                App()
            }
        }
    }
    googleLoginInterface.setController(controller)
    return controller
}
then you can access the view using the
LocalLottieInterfaceFactory.current
and this will return an object of
LottieInterface
then you know what to do with UIKitView in compose
for this i've experimented 2 days and yesterday i've solved it with this pully method
l
Thank you very much. Do you think this will correctly support setting a property to that specific view ?
d
Sorry for long answer. Do you still have some questions regarting this thread?