icerockdev / moko-kswift

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

Generated enum does not conform to Codable #94

Closed jollygreenegiant closed 2 months ago

jollygreenegiant commented 3 months ago

I have the following Swift code:

public protocol Destination: Codable, Hashable { }

public enum HomeDestination: Destination {
    case scanBook
    case batchScanBook
    case addBookManually
    case bookDetail(id: String, bookType: BookTypeKs)
}

and BookTypeKs is generated like this:

public enum BookTypeKs {

  case isbnBookType(BookType.IsbnBookType)
  case otherUsersBookType(BookType.OtherUsersBookType)
  case remoteBookType(BookType.RemoteBookType)
  case unknownBookType(BookType.UnknownBookType)
  case userBookType

  public var sealed: BookType {
    switch self {
    case .isbnBookType(let obj):
      return obj as shared.BookType
    case .otherUsersBookType(let obj):
      return obj as shared.BookType
    case .remoteBookType(let obj):
      return obj as shared.BookType
    case .unknownBookType(let obj):
      return obj as shared.BookType
    case .userBookType:
      return shared.BookType.UserBookType() as shared.BookType
    }
  }

  public init(_ obj: BookType) {
    if let obj = obj as? shared.BookType.IsbnBookType {
      self = .isbnBookType(obj)
    } else if let obj = obj as? shared.BookType.OtherUsersBookType {
      self = .otherUsersBookType(obj)
    } else if let obj = obj as? shared.BookType.RemoteBookType {
      self = .remoteBookType(obj)
    } else if let obj = obj as? shared.BookType.UnknownBookType {
      self = .unknownBookType(obj)
    } else if obj is shared.BookType.UserBookType {
      self = .userBookType
    } else {
      fatalError("BookTypeKs not synchronized with BookType class")
    }
  }

}

The Kotlin class is defined like this:

sealed class BookType {
    object UserBookType: BookType()
    data class RemoteBookType(val workId: String): BookType()
    data class UnknownBookType(
        val workId: String
    ): BookType()
    data class IsbnBookType(val isbn: String): BookType()
    data class OtherUsersBookType(val id: String): BookType()

    fun getNavString(): String {
        return when (this) {
            is UserBookType -> "user_book"
            is RemoteBookType -> "remote_book"
            is UnknownBookType -> "unknown_book"
            is IsbnBookType -> "isbn_book"
            is OtherUsersBookType -> "other_users_book"
        }
    }

    companion object {
        fun fromNavString(navString: String): BookType {
            return when (navString) {
                "user_book" -> UserBookType
                "remote_book" -> RemoteBookType(workId = "")
                "unknown_book" -> UnknownBookType(workId = "")
                "isbn_book" -> IsbnBookType(isbn = "")
                "other_users_book" -> OtherUsersBookType(id = "")
                else -> throw IllegalArgumentException("Invalid nav string: $navString")
            }
        }
    }
}

I'm getting the error Type 'HomeDestination' does not conform to protocol 'Codable/Decodable/Equatable/Hashable'

Is there a way to get Moko to generate enum classes that do conform to those protocols? Or at least a simple way to manually make them conform?

My Swift skills aren't particularly strong, and this is something I've run into multiple times now working in KMM and would love to know how to fix for the future.

Alex009 commented 3 months ago

Create extension in swift to generated enum with required protocol

jollygreenegiant commented 3 months ago

@Alex009 could you elaborate on that a little bit? I'm a Kotlin developer by trade, not Swift, so I'm not super familiar with what that might look like

Alex009 commented 3 months ago

@jollygreenegiant you can declare your own extension in your code

extension BookTypeKs: Codable, Hashable {
    ...
}