Hello, I have KMP module which is shared for iOS a...
# multiplatform
t
Hello, I have KMP module which is shared for iOS and Android client. On android everything is working good. However when I run iOS client we start to get this error:
Copy code
2021-05-14 10:05:02.962001+0200 sts[1040:3855803] KMP_ClosedTicket: state: loading
Function doesn't have or inherit @Throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError.
It is considered unexpected and unhandled instead. Program will be terminated.
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen com.betsys.util.PlatformCache@28c4da8
The PlatformCache object which throws this error looks like this:
Copy code
object PlatformCache {
    var isLogsEnabled: Boolean = false
        private set

    fun setIsLogEnabled(isEnabled: Boolean) {
        isLogsEnabled = isEnabled
    }
}
As far as I understand this error is thrown when our logger instance acces the isLogsEnabled field from Logger.
Copy code
actual open class Logger {
    actual companion object {
        actual val INSTANCE: Logger
            get() = Logger()
    }

    actual open fun v(msg: String) {
        log(msg)
    }

    actual open fun d(msg: String) {
        log(msg)
    }

    actual open fun i(msg: String) {
        log(msg)
    }

    actual open fun w(msg: String) {
        log(msg)
    }

    actual open fun e(error: Throwable, msg: String) {
        log(msg, error)
    }

    private fun log(msg: String, error: Throwable? = null) {
        // Set by BSPlatform
        if (PlatformCache.isLogsEnabled) {
            if (error == null) {
                println("❤️ KMPLog: $msg")
            } else {
                println("❤️ KMPLog: $msg  error: ${error.message}")
            }
        }
    }
}
Do you have some idea on how to avoid this crash? I do not know anything about freezing in K/N. 🙂
k
The quickest solution is to use `AtomicBoolean`:
Copy code
object PlatformCache {

    private val _isLogsEnabled: AtomicBoolean = AtomicBoolean(false)
    val isLogsEnabled: Boolean  
        get() = _isLogsEnabled.value
    
    fun setIsLogEnabled(isEnabled: Boolean) {
        _isLogsEnabled.value = isEnabled
    }
}
however I recommend to learn why it’s needed 🙂
t
Thank you. :)
t
Thank you for the reference 🙂 Will take a look 🙂