icerockdev / moko-kswift

Swift-friendly api generator for Kotlin/Native frameworks
https://moko.icerock.dev
Apache License 2.0
350 stars 21 forks source link

Bad interop with swift Arrays #74

Closed Borlehandro closed 1 year ago

Borlehandro commented 1 year ago

Hello everyone! I convert my sealed class to swift enum:

sealed class LoadableState<out T> {

    object Initial : LoadableState<Nothing>()

    object Loading : LoadableState<Nothing>()

    class Success<T>(val data: T) : LoadableState<T>()

    class Error private constructor(
        val throwable: Throwable?,
        val message: String?,
    ) : LoadableState<Nothing>() {

        constructor(throwable: Throwable) : this(throwable, throwable.message)

        constructor(message: String?) : this(null, message)
    }
}

kswift converts it to the enum

public enum LoadableStateKs<T : AnyObject> {

  case error(LoadableStateError)
  case initial
  case loading
  case success(LoadableStateSuccess<T>)

  public var sealed: LoadableState<T> {
    switch self {
    case .error(let obj):
      return obj as! MultiPlatformLibrary.LoadableState<T>
    case .initial:
      return MultiPlatformLibrary.LoadableStateInitial() as! MultiPlatformLibrary.LoadableState<T>
    case .loading:
      return MultiPlatformLibrary.LoadableStateLoading() as! MultiPlatformLibrary.LoadableState<T>
    case .success(let obj):
      return obj as MultiPlatformLibrary.LoadableState<T>
    }
  }

  public init(_ obj: LoadableState<T>) {
    if let obj = obj as? MultiPlatformLibrary.LoadableStateError {
      self = .error(obj)
    } else if obj is MultiPlatformLibrary.LoadableStateInitial {
      self = .initial
    } else if obj is MultiPlatformLibrary.LoadableStateLoading {
      self = .loading
    } else if let obj = obj as? MultiPlatformLibrary.LoadableStateSuccess<T> {
      self = .success(obj)
    } else {
      fatalError("LoadableStateKs not synchronized with LoadableState class")
    }
  }

}

Now, in my shared module I use LoadableState<List<CustomObject>> but on the Swift side i can’t use LoadableStateKs<Array<CustomObject>> because LoadableStateKs requires generic argument to be subclass of AnyObject. Maybe I understand this behaviour wrongly, can anyone explain it, please?

Alex009 commented 1 year ago

Kotlin/Native not give Array, it give object - NSArray

Borlehandro commented 1 year ago

Yes, I understand Kotlin/Native give NSArray. I just thought LoadableStateKs could be generated another way to support Arrays) After research I understand that it probably will be possible only with direct Kotlin - Swift interop. For my case using wrapper around this list helps to make work on Swift side more comfortable. This issues is closed, thank you!