1

I'm using KMP to make a crossplatform app both on Android and iOS. My problem is that when I create an interface in Kotlin common main with a default implementation, I can't use that implementation in iOS and I need to rewrite the code in Xcode. Inside my methods there is nothing platform-specific. They are just functions that work with numbers (so, just some for or if with a return numeric parameter) so could very good for me write the methods just one time. There is a way to achive this?

This is the interface in Kotlin with the method and default implementation:

interface StandardValues {
fun nextValue(valueToCompare: String, currentStandardSpinner: String, currentUnitSpinner: Int): Pair<String, Int> {

    var currentStandardArray = StandardValue.E12.valuesStandard
    var indexSpinner = currentUnitSpinner
    var valueConverted = 0.0f

    try{
        valueConverted = valueToCompare.toFloat()
    } catch (e: NumberFormatException){
        e.printStackTrace()
        println(e)
    }

    if(valueToCompare.isNotEmpty()){
        var previousValue: Float = 0.0f

        if(valueConverted <= 1 && currentUnitSpinner == 0){
            return Pair("0",0)
        }
        if(valueConverted < 1) {
            for ((index, value) in currentStandardArray.withIndex()){
                if ((valueConverted * 1000) > value){
                    previousValue = currentStandardArray[index]
                }
            }
            if(indexSpinner != 0){
                indexSpinner--
            }
            return Pair(previousValue.toString(), indexSpinner)
        }
        if(valueConverted <= currentStandardArray.first()){
            if(indexSpinner == 0){
                return Pair(currentStandardArray.first().toString(), 0)
            }
            previousValue = currentStandardArray.last()
            indexSpinner--
            return Pair(previousValue.toString(), indexSpinner)
        }
        for ((index, value) in currentStandardArray.withIndex()){
            if (valueConverted > value){
                previousValue = currentStandardArray[index]
            }
        }
        return Pair(previousValue.toString(), indexSpinner)
    }
    return Pair(currentStandardArray.first().toString(), indexSpinner)
}

This is an example of use in Android:

class FindRealComponent: AppCompatActivity(), AdapterView.OnItemSelectedListener, StandardValues {
...
myTextView.text = nextValue("3", "pF", 0).first
}

In Xcode:

class MeasureConverterViewController: UIViewController, StandardValues {
    
    func nextValue(valueToCompare: String, currentStandardSpinner: String, currentUnitSpinner: Int) -> (String, Int) { 
        //I would like to avoid to write the same logic code

   }
textView.text = nextValue(nextValue("3", "pF", 0).0
...
}

Otherwise I think that i will implements the interface in Kotlin and I will create a protocol with an extension in Swift.

Thanks.

patana93
  • 73
  • 1
  • 8
  • Thanks, I've added the code. I didn't write it because my question is: how to use default method implementation (written in Android Studio with Kotlin) in Xcode in general :) I aplogize for the error. – patana93 Oct 04 '20 at 16:49
  • Kotlin interface maps to protocol in ObjC. Which means it cannot have default implementation there. You need to change this to class from interface and use composition when consuming this class. – Dmitri Oct 08 '20 at 01:28
  • Thanks for the reply. To resolve I have implemented the interface in Android Studio and in the same file I have created a class that implement my interface thus in Xcode so I can instantiate an object of that class to use the default methods. Could be a correct solution? – patana93 Oct 10 '20 at 13:08

1 Answers1

2

To resolve I have implemented the interface in Android Studio and in the same file I have created a class that implement my interface so in Xcode I can instantiate an object of that class to use the default methods.

Android Studio:

interface StandardValues { 
... //default methods 
} 

class StandardValuesImplementation: StandardValues{} 

Xcode:

class MyViewController: UIViewController{ 
... 
override func viewDidLoad() { 
super.viewDidLoad() 
... 
let myClassImpl = StandardValuesImplementation() 
let textView = MyClassImpl.myDefaultMethod 
...
}
patana93
  • 73
  • 1
  • 8
  • 2
    This was helpful - thanks! In my case, I also wanted to extend the class in Xcode with some Swift-specific implementation details for one method, and in order to do this I needed to mark the shared class (`StandardValuesImplementation` in your example) as `open class` to do that. – Derek Lee Jan 31 '21 at 13:23