Hi ! I'm having some dependencies issues with KMP ...
# ios
a
Hi ! I'm having some dependencies issues with KMP and iOS Framework. I have the following architecture: 2 KMP modules: • KMPlibAPI: contains only interfaces • KMPlib: contains implementations and usages of KMPlibAPI When I build the KMPlib, the header include the KMPlibAPI definition. But I didn't wanted to be included in my KMPlib framework, I just wanted to have a needed references to KMPlibAPI. Exemple of what I have:
Copy code
//KMPlibAPI.h
@protocol KMPAPIFoo
@required
- (void)bar __attribute__((swift_name("bar()")));
@end;


//KMPlib.h
@protocol KAFoo  // <----- here we have a redefinition of the protocol.
@required
- (void)bar __attribute__((swift_name("bar()")));
@end;

@interface Baz
- (void)injectFoo:(KAFoo)foo  __attribute__((swift_name("injectFoo(foo:)"))); // <----- and here we are using it, instead of using KMPAPIFoo
@end;
I've tried to put the dependencies in
compileOnly
into gradle, but nothing changed. Anyone is confortable with gradle compilation option for Kotlin native and dependencies ?
l
Hello,
compileOnly
isn't supported in Kotlin/Native. The solution is to set the visibility of implementation details to
internal
a
Hello Louis, What do you mean by "set the visibility of implementation details to `internal`" ? The aim of splitting the API and the injection is to have the following behavior : 2 ios Project: • 1 swift package • 1 iOS app the swift package have the following implementation :
Copy code
import KMPlibAPI

public class SampleFoo: NSObject, Foo {
   func bar() { } 
}
and into the app
Copy code
import KMPlib
import MySwiftPackage

let foo = SampleFoo()

let baz = Baz()
baz.injectFoo(foo)
As you can see, I can't set
injectFoo
to
internal
here, otherwise I won't be able to call it through the iOS app. I'm not sure if I made it clear ?
l
Then don't make
injectFoo
internal, but make the rest
internal
?
a
What do you call the rest ? the
baz
class ?
l
Whatever you don't want to expose to Swift.
a
Yes but as soon as I expose
injectFoo(foo:Foo)
into the KMPlib, it will include the Foo protocol into the KMPlib.h and that's my point, I don't want to have the protocol exposed in the KMPlib.h but have a reference to the KMPlibAPI.h (which contain the
Foo
protocol)
l
I think what you want to do with what you have is simply impossible. Even in pure Kotlin, it's impossible to have a public declaration exposing an internal or private type.
a
yes yes, none of them are private or internal, everything is public here
l
Then, that's it, right?
a
Hmmm not really. In kotlin I can do what I wanted. For example:
Copy code
// API project
public interface Foo

// libA project
public class Bar {
    fun doSomething(foo: Foo)
}

// libB project
import API

public class FooImpl: Foo { }

// android app
import libA
import libB

var foo = FooImpl()
var bar = Bar()
bar.doSomething(foo) // <----- Everything is fine here
but in iOS I can't:
Copy code
// ios app
import libA
import libB

var foo = FooImpl()
var bar = Bar()
bar.doSomething(foo) // <----- Error here : FooImpl is of type APIFoo but here LibAAPIFoo is excpected
because I have the folowing headers :
Copy code
/// API.h
@protocol APIFoo
Copy code
// libA.h
@protocol LibAAPIFoo

@interface Bar
- (void)injectFoo:(LibAAPIFoo)foo
@end;
l
So much "foo", I have a really hard time wrapping my head around to be honest.
a
Haha I understand, maybe I can host it on a github, it will probably be clearer.
l
I don't think I'll take the time, but I can tell you one thing: Swift protocols are not a 100% translation of interfaces in Kotlin (or Java), so that can explain some differences in the semantics. You might be able to work that around by using an abtract class with all abstract functions/properties.
a
Ok, thank you for your time