Home > Developer Guide > Guides > Kotlin-Swift Type Mappings


Kotlin-Swift Type Mappings Quick Reference

Purpose: Quick reference for Kotlin → Swift type conversions when building iOS frameworks

For comprehensive guide: See Kotlin-Swift Type Interoperability

Discovered: During PR #269 iOS build after Firebase BOM resolution

Overview

When Kotlin code is compiled to an iOS framework, types are automatically mapped to Swift equivalents. Understanding these mappings prevents compilation errors in Swift code consuming the framework.

This guide provides the essential type mapping table. For detailed patterns, troubleshooting, and code examples, see the comprehensive interop guide.


Core Type Mappings

Numeric Types

Kotlin TypeKotlin SizeSwift TypeSwift SizeNotes
Byte8-bitInt88-bitSigned byte
Short16-bitInt1616-bitSigned short
Int32-bitInt3232-bitMost common issue
Long64-bitInt6464-bitSecond most common
Float32-bitFloat32-bitAuto-converts
Double64-bitDouble64-bitAuto-converts
UByte8-bit unsignedUInt88-bit unsignedUnsigned byte
UShort16-bit unsignedUInt1616-bit unsignedUnsigned short
UInt32-bit unsignedUInt3232-bit unsignedUnsigned int
ULong64-bit unsignedUInt6464-bit unsignedUnsigned long

String and Boolean

Kotlin TypeSwift TypeNotes
StringStringAuto-converts
String?String?Auto-converts
BooleanBoolAuto-converts
Boolean?Bool?Auto-converts

Collections

Kotlin TypeSwift TypeNotes
List<T>[T]Auto-converts
List<T>?[T]?Auto-converts
Set<T>Set<T>Auto-converts
Map<K,V>Dictionary<K,V>Auto-converts
Array<T>[T]Auto-converts

Special Cases

Kotlin TypeSwift TypeNotes
UnitVoidFunction return type
AnyAnyTop type
Any?Any?Nullable top type
EnumStatic propertiesNo rawValue initializer

Critical: Required vs Optional Parameters

Most Common Mistake: Kotlin optional numeric types require wrapper classes in Swift

Kotlin ParameterSwift Required ParameterSwift Optional Parameter
val x: IntInt32 (auto-converts ✅)N/A
val x: Int?N/AKotlinInt? (must wrap ⚠️)
val x: LongInt64 (auto-converts ✅)N/A
val x: Long?N/AKotlinLong? (must wrap ⚠️)
val x: String?N/AString? (auto-converts ✅)
val x: Boolean?N/ABool? (auto-converts ✅)

Key Rule:

  • Optional numerics: Must be wrapped (KotlinInt?, KotlinLong?)
  • Optional strings/bools: Auto-convert, no wrapper
  • Required parameters: All types auto-convert

PR #269 iOS Build Errors

The Problem

After fixing Firebase BOM issue, iOS build in Xcode showed:

TournamentListViewModel.swift:158:97 Cannot convert value of type 'Int' to expected argument type 'Int32'
TournamentListViewModel.swift:159:97 Cannot convert value of type 'Int' to expected argument type 'Int32'
TournamentListViewModel.swift:173:94 Cannot convert value of type 'Int' to expected argument type 'Int32'

Root Cause

Kotlin definition:

data class TournamentSecuritySettings(
    val maxScoreCorrections: Int = 3,        // Kotlin Int (32-bit)
    val correctionTimeLimit: Int = 300       // Kotlin Int (32-bit)
)
 
data class TournamentPrivacySettings(
    val dataRetentionDays: Int = 90          // Kotlin Int (32-bit)
)

Swift code (WRONG):

let securitySettings = TournamentSecuritySettings(
    maxScoreCorrections: sec["maxScoreCorrections"] as? Int ?? 3,      // ❌ Swift Int (64-bit)
    correctionTimeLimit: sec["correctionTimeLimit"] as? Int ?? 300     // ❌ Swift Int (64-bit)
)
 
let privacySettings = TournamentPrivacySettings(
    dataRetentionDays: priv["dataRetentionDays"] as? Int ?? 90         // ❌ Swift Int (64-bit)
)

Problem:

  • Kotlin Int → Swift Int32 in generated framework
  • Swift Int is platform-dependent (64-bit on modern iOS devices)
  • Type mismatch: Int vs Int32

The Fix

Swift code (CORRECT):

let securitySettings = TournamentSecuritySettings(
    maxScoreCorrections: sec["maxScoreCorrections"] as? Int32 ?? 3,    // ✅ Int32
    correctionTimeLimit: sec["correctionTimeLimit"] as? Int32 ?? 300   // ✅ Int32
)
 
let privacySettings = TournamentPrivacySettings(
    dataRetentionDays: priv["dataRetentionDays"] as? Int32 ?? 90       // ✅ Int32
)

Commit: fe1a2403 - fix: Change Int to Int32 for Kotlin framework compatibility

Source: iosApp/ArcheryApprentice/ArcheryApprentice/TournamentListViewModel.swift:158-173


Common Errors and Fixes

Error: Cannot convert ‘Int’ to ‘Int32’

Error Message:

Cannot convert value of type 'Int' to expected argument type 'Int32'

Cause: Using Swift Int where Kotlin Int (Int32) is expected

Fix:

- value as? Int
+ value as? Int32

Error: Cannot convert ‘Int64?’ to ‘KotlinLong?’

Error Message:

Cannot convert value of type 'Int64?' to expected argument type 'KotlinLong?'

Cause: Optional Kotlin Long? requires KotlinLong? wrapper

Fix:

- value?.int64Value
+ value.map { KotlinLong(longLong: $0.int64Value) }

Error: Cannot convert ‘Int32?’ to ‘KotlinInt?’

Error Message:

Cannot convert value of type 'Int32?' to expected argument type 'KotlinInt?'

Cause: Optional Kotlin Int? requires KotlinInt? wrapper

Fix:

- Int32(truncating: value)
+ value.map { KotlinInt(int: Int32(truncating: $0)) }

Firebase NSNumber Conversions

When parsing Firebase Firestore data (which returns NSNumber), follow these patterns:

Required Int32 Parameter

// Kotlin: val numEnds: Int
let numEnds = Int32(truncating: (data["numEnds"] as? NSNumber) ?? 6)

Required Int64 Parameter

// Kotlin: val createdAt: Long
let createdAt = (data["createdAt"] as? NSNumber)?.int64Value ?? 0

Optional Int32 Parameter

// Kotlin: val timeLimit: Int?
let timeLimit = (data["timeLimit"] as? NSNumber).map { KotlinInt(int: Int32(truncating: $0)) }

Optional Int64 Parameter

// Kotlin: val startTime: Long?
let startTime = (data["startTime"] as? NSNumber).map { KotlinLong(longLong: $0.int64Value) }

Quick Decision Tree

When writing Swift code that calls Kotlin:

Is the parameter a number (Int/Long)?
│
├─ YES → Is it optional (Int? / Long?)?
│        │
│        ├─ YES → Use wrapper (KotlinInt? / KotlinLong?)
│        │        Examples:
│        │        - KotlinInt(int: Int32(...))
│        │        - KotlinLong(longLong: Int64(...))
│        │
│        └─ NO  → Use Int32 or Int64 directly
│                 Examples:
│                 - Int32(truncating: nsNumber)
│                 - nsNumber?.int64Value
│
└─ NO  → Is it String, Bool, or Array?
         │
         └─ YES → Auto-converts, no wrapper needed
                  (works for both required and optional)

Testing Checklist

When updating Kotlin models used in iOS:

  • Check if any properties are numeric types (Int, Long)
  • Build iOS framework (./gradlew linkDebugFrameworkIosSimulatorArm64)
  • Open iOS project in Xcode
  • Build project (⌘B)
  • Check for type conversion errors
  • Fix any IntInt32 or LongInt64 mismatches
  • Verify optional parameters use wrappers where needed

Comprehensive Guides:

Related Sessions:

External Resources:


Key Takeaways

  1. Kotlin Int → Swift Int32 (not Swift Int)
  2. Kotlin Long → Swift Int64 (not Swift Int)
  3. Optional numerics need wrappers (KotlinInt?, KotlinLong?)
  4. Strings and Bools auto-convert (no wrappers needed)
  5. Always check iOS build after modifying Kotlin models
  6. Test both required and optional parameters separately

Status: Active - Type mappings validated during PR #269 iOS build

Last Updated: 2025-11-18 Related PRs: #269 (Firebase BOM + iOS type fixes) Week: 28