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 Type | Kotlin Size | Swift Type | Swift Size | Notes |
|---|---|---|---|---|
Byte | 8-bit | Int8 | 8-bit | Signed byte |
Short | 16-bit | Int16 | 16-bit | Signed short |
Int | 32-bit | Int32 | 32-bit | Most common issue |
Long | 64-bit | Int64 | 64-bit | Second most common |
Float | 32-bit | Float | 32-bit | Auto-converts |
Double | 64-bit | Double | 64-bit | Auto-converts |
UByte | 8-bit unsigned | UInt8 | 8-bit unsigned | Unsigned byte |
UShort | 16-bit unsigned | UInt16 | 16-bit unsigned | Unsigned short |
UInt | 32-bit unsigned | UInt32 | 32-bit unsigned | Unsigned int |
ULong | 64-bit unsigned | UInt64 | 64-bit unsigned | Unsigned long |
String and Boolean
| Kotlin Type | Swift Type | Notes |
|---|---|---|
String | String | Auto-converts |
String? | String? | Auto-converts |
Boolean | Bool | Auto-converts |
Boolean? | Bool? | Auto-converts |
Collections
| Kotlin Type | Swift Type | Notes |
|---|---|---|
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 Type | Swift Type | Notes |
|---|---|---|
Unit | Void | Function return type |
Any | Any | Top type |
Any? | Any? | Nullable top type |
| Enum | Static properties | No rawValue initializer |
Critical: Required vs Optional Parameters
Most Common Mistake: Kotlin optional numeric types require wrapper classes in Swift
| Kotlin Parameter | Swift Required Parameter | Swift Optional Parameter |
|---|---|---|
val x: Int | Int32 (auto-converts ✅) | N/A |
val x: Int? | N/A | KotlinInt? (must wrap ⚠️) |
val x: Long | Int64 (auto-converts ✅) | N/A |
val x: Long? | N/A | KotlinLong? (must wrap ⚠️) |
val x: String? | N/A | String? (auto-converts ✅) |
val x: Boolean? | N/A | Bool? (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→ SwiftInt32in generated framework - Swift
Intis platform-dependent (64-bit on modern iOS devices) - Type mismatch:
IntvsInt32
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? Int32Error: 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 ?? 0Optional 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
Int→Int32orLong→Int64mismatches - Verify optional parameters use wrappers where needed
Related Documentation
Comprehensive Guides:
- Kotlin-Swift Type Interoperability - Full guide with patterns, troubleshooting, and examples
Related Sessions:
- PR #269 Debugging Session - Where these type errors appeared
- Week 28 iOS Firebase Integration - iOS framework setup and @SerialName fix
External Resources:
- Kotlin/Native Interop Documentation - Official Kotlin → Swift/Objective-C interop guide
- KMP-NativeCoroutines - Flow → AsyncSequence conversion library
Key Takeaways
- Kotlin
Int→ SwiftInt32(not SwiftInt) - Kotlin
Long→ SwiftInt64(not SwiftInt) - Optional numerics need wrappers (
KotlinInt?,KotlinLong?) - Strings and Bools auto-convert (no wrappers needed)
- Always check iOS build after modifying Kotlin models
- 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