Cheeseburger
Cheeseburger

Reputation: 225

Calling class in swift from kotlin/native framework

I followed the tutorial: https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html and successfully export a jar file for Android and a framework for iOS. After I want to implement something more complex. I uses Android Studio Kotlin with the codes below:

Model.kt:

package org.kotlin.mpp.mobile.BusinessLogic

abstract class Model{

var _id:Long = 0

abstract fun PolymorphismTest()
}

Sales.kt:

package org.kotlin.mpp.mobile.BusinessLogic

class Sales : Model() {

init {
    this._id = _counter
    _counter++

}
companion object {

    private var _counter: Long = 0

}

fun get_counter(): Long {
    return _counter
}

private val _salesItems:MutableList<SalesItem> = ArrayList()

fun SalesItems(): MutableList<SalesItem> {
    return _salesItems
}

fun TotalAmount():Double
{
    var totalAmount:Double = 0.0
    for(aSalesItem in _salesItems)
    {
        totalAmount += aSalesItem.SubTotal()
    }

    return totalAmount
}

fun AddSalesItem(salesItem: SalesItem)
{
    this._salesItems.add(salesItem)
}

fun AddSalesItem(itemName:String, itemCode:String, quantity:Double, amount:Double )
{
    val aSalesItem = SalesItem()
    aSalesItem._itemCode = itemCode
    aSalesItem._itemName = itemName
    aSalesItem._quantity = quantity
    aSalesItem._amount = amount
    this.AddSalesItem(aSalesItem)
}

fun ToString(): String {
    return "Sales: $this._id"
}


override fun PolymorphismTest() {
    println("This is method from Sales")
}

}

SalesItem.kt:

package org.kotlin.mpp.mobile.BusinessLogic

class SalesItem : Model() {

init {
    this._id = _counter
    _counter++
}
companion object {

    private var _counter: Long = 0
}

fun get_counter(): Long {
    return _counter
}

var _sales: Sales? = null

var _amount:Double = 0.toDouble()
var _quantity:Double = 0.toDouble()

fun SubTotal(): Double {
    return _amount * _quantity
}

var _itemName:String? = null
var _itemCode:String? = null


fun Sales():Sales?{
    return _sales
}

fun SalesItem(sales:Sales)
{
    _sales = sales
    this._id = _counter
    _counter++
}

fun ToString(): String {
    return "Sales: $this._id"
}

override fun PolymorphismTest() {
    println("This is method from SalesItem")
}
}

I export these codes into a framework then imported into Xcode and using Swift to call

ViewController.swift

import UIKit
import SharedCode
class ViewController: UIViewController{

override func viewDidLoad(){
     super.viewDidLoad()

     print("Creating Sales Object")
     let sales = Sales() //error here

   }
 }

After that I met the errors of

Instances of kotlin.Error, kotlin.RuntimeException and subclasses aren't propagated from Kotlin to Objective-C/Swift. Other exceptions can be propagated as NSError if method has or inherits @Throws annotation. Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen org.kotlin.mpp.mobile.BusinessLogic.Sales.Companion@228b588 at 0 SharedCode

Upvotes: 2

Views: 3219

Answers (1)

Eugene Petrenko
Eugene Petrenko

Reputation: 4992

Kotlin/Native has different threading model. The idea is that an instance of an object has to be frozen to be accessed from all threads. There is .freeze() extension method for that.

By default, object Smth are also frozen. In the code sniper you have mutable fields in companion object.

A possible workaround could be to replace companion object with an ordinary class, that you create explicitly

https://kotlinlang.org/docs/reference/native/concurrency.html#concurrency-in-kotlinnative

https://kotlinlang.org/docs/reference/native/immutability.html#immutability-in-kotlinnative

Upvotes: 2

Related Questions