NSErrorKt - A Kotlin Multiplatform Library to improve NSError interop

Overview

NSErrorKt

A Kotlin Multiplatform Library to improve NSError interop.

WARNING: This is an experiment to try and improve Kotlin's NSError interop.
To achieve this the library exposes some Kotlin internals that aren't part of any public API!

Why do we need this?

Kotlin already has Throwable to NSError interop for straightforward cases as described in the docs.
Though currently there is no way for application or library code to use this interop directly, meaning applications and libraries need to create their own instead.

Ktor

The Ktor Darwin client does this by wrapping a NSError in a custom Exception:

@OptIn(UnsafeNumber::class)
internal fun handleNSError(requestData: HttpRequestData, error: NSError): Throwable = when (error.code) {
    NSURLErrorTimedOut -> SocketTimeoutException(requestData)
    else -> DarwinHttpRequestException(error)
}

Which is a great solution for your Kotlin code as it allows you to access the wrapped NSError.
However once these Exceptions reach Swift/ObjC, Kotlin will convert them to a NSError.
Since Kotlin doesn't know this Exception is a wrapped NSError it will wrap the Exception in a NSError again.

This results in hard to log errors like this one.

KMP-NativeCoroutines

KMP-NativeCoroutines has a similar problem where it needs to convert Exceptions to NSErrors:

@OptIn(UnsafeNumber::class)
internal fun Throwable.asNSError(): NSError {
    val userInfo = mutableMapOf<Any?, Any>()
    userInfo["KotlinException"] = this.freeze()
    val message = message
    if (message != null) {
        userInfo[NSLocalizedDescriptionKey] = message
    }
    return NSError.errorWithDomain("KotlinException", 0.convert(), userInfo)
}

It produces similar NSErrors to the once Kotlin creates, but it doesn't unwrap an already wrapped NSError.
And in case such an NSError reaches Kotlin again it will be wrapped in an Exception instead of being unwrapped.

So depending on your code this might result in hard to log errors as well.

Usage

To solve these issues this library exposes the Kotlin NSError interop logic to your application and library code.

Consisting of 3 extension functions:

and 2 extension properties:

asNSError

/**
 * Converts `this` [Throwable] to a [NSError].
 *
 * If `this` [Throwable] represents a [NSError], the original [NSError] is returned.
 * For other [Throwable]s a `KotlinException` [NSError] is returned:
 * ```
 * NSError.errorWithDomain("KotlinException", 0, mapOf(
 *     "KotlinException" to this,
 *     NSLocalizedDescriptionKey to this.message
 * ))
 * ```
 *
 * @see throwAsNSError
 * @see asThrowable
 */
fun Throwable.asNSError(): NSError

throwAsNSError

/**
 * Tries to convert `this` [Throwable] to a [NSError].
 *
 * If `this` [Throwable] is an instance of one of the [exceptionClasses] or their subclasses,
 * it is converted to a [NSError] in the same way [asNSError] would.
 *
 * Other [Throwable]s are considered unhandled and will cause program termination
 * in the same way a [Throws] annotated function would.
 *
 * @see asNSError
 * @see asThrowable
 * @see Throws
 */
fun Throwable.throwAsNSError(vararg exceptionClasses: KClass<out Throwable>): NSError

asThrowable

/**
 * Converts `this` [NSError] to a [Throwable].
 *
 * If `this` [NSError] represents a [Throwable], the original [Throwable] is returned.
 * For other [NSError]s an [ObjCErrorException] will be returned.
 *
 * @see asNSError
 */
fun NSError.asThrowable(): Throwable

isNSError

/**
 * Indicates if `this` [Throwable] represents a [NSError].
 */
val Throwable.isNSError: Boolean

isThrowable

/**
 * Indicates if `this` [NSError] represents a [Throwable].
 */
val NSError.isThrowable: Boolean
You might also like...
Kotlin Multiplatform (KMP) library for reading resources in tests

kotlinx-resources Kotlin Multiplatform (KMP) plugin and library that add support for reading resources in tests. The plugin and a library work in tand

Kotlinx-murmurhash - Kotlin Multiplatform (KMP) library for hashing using MurmurHash

kotlinx-murmurhash Kotlin Multiplatform (KMP) library for MurmurHash, a non-cryp

Semantic Versioning library for Kotlin Multiplatform.

kotlin-semver Semantic Versioning library for Kotlin Multiplatform. It implements the full semantic version 2.0.0 specification and provides ability t

A Kotlin multiplatform unit testing library inspired by / similar to Google Truth.

Truthish A testing API inspired by Google Truth but rewritten in Kotlin from the ground up, so it can be used in Kotlin multiplatform projects. For ex

A library for working with URIs in Kotlin Multiplatform

Uri KMP Most of this work is derived from AOSP's Uri: Uri.java UriCodec.java UriTest.java UriCodecTest.java Gradle Groovy repositories { mavenCentra

A tiny Kotlin multiplatform library that assists in saving and restoring objects to and from disk using kotlinx.coroutines, kotlinx.serialisation and okio

Store A tiny Kotlin multiplatform library that assists in saving and restoring objects to and from disk using kotlinx.coroutines, kotlinx.serialisatio

Opinionated Redux-like implementation backed by Kotlin Coroutines and Kotlin Multiplatform Mobile

CoRed CoRed is Redux-like implementation that maintains the benefits of Redux's core idea without the boilerplate. No more action types, action creato

An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.
An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile.

An app architecture for Kotlin/Native on Android/iOS. Use Kotlin Multiplatform Mobile. 项目架构主要分为原生系统层、Android/iOS业务SDK层、KMM SDK层、KMM业务逻辑SDK层、iOS sdkfra

Dependency Injection library for Compose Multiplatform, Koin wrapper.

🥥 Cokoin Injection library for Compose (Multiplatform and Jetpack), Koin wrapper. It uses @Composable functions to configure KoinContext and Scopes.

Owner
Rick Clephas
Attempting to create the apps of the future
Rick Clephas
A multi module app, for improve knowledges

MultiModuleApp App multimódulos para estudos Aqui existem vários apps simples (1 em cada módulo) e está sendo construído por: App multi módulos Consum

PLINIO DA SILVA ALENCAR 0 Dec 27, 2021
A Addon created to improve experience of playing with Meteor Client

A Addon created to improve experience of playing with Meteor Client

мяучер 14 Nov 7, 2022
Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in Kotlin with Jetpack Compose and a backed in Kotlin hosted on AppEngine.

Conferences4Hall Real life Kotlin Multiplatform project with an iOS application developed in Swift with SwiftUI, an Android application developed in K

Gérard Paligot 98 Dec 15, 2022
A Bluetooth kotlin multiplatform "Cross-Platform" library for iOS and Android

Blue-Falcon A Bluetooth "Cross Platform" Kotlin Multiplatform library for iOS, Android, MacOS, Raspberry Pi and Javascript. Bluetooth in general has t

Andrew Reed 220 Dec 28, 2022
Dependency Injection library for Kotlin Multiplatform, support iOS and Android

Multiplatform-DI library for Kotlin Multiplatform Lightweight dependency injection framework for Kotlin Multiplatform application Dependency injection

Anna Zharkova 32 Nov 10, 2022
Kotlin multiplatform library template.

template-kmp-library Kotlin multiplatform library template. Has a baseline setup for a multiplatform library supporting all kotlin targets except andr

Martynas Petuška 51 Nov 21, 2022
Generic AST parsing library for kotlin multiplatform

kotlinx.ast kotlinx.ast is a generic AST (Abstract Syntax Tree) parsing library, Kotlin is currently the only supported language. The library is desig

null 235 Dec 29, 2022
Server Sent Events (SSE) client multiplatform library made with Kotlin and backed by coroutines

OkSSE OkSSE is an client for Server Sent events protocol written in Kotlin Multiplatform. The implementation is written according to W3C Recommendatio

BioWink GmbH 39 Nov 4, 2022
A local storage management library for Kotlin Multiplatform Mobile iOS and android

A local storage management library for Kotlin Multiplatform Mobile iOS and android Features iOS and Android local storage in one interface Provides ge

LINE 20 Oct 30, 2022
Kotlin multiplatform library template

template-kmp-library Kotlin multiplatform library template. Has a baseline setup for a multiplatform library supporting all kotlin targets except depr

Jamie Astley 0 Dec 6, 2021