Introduction
Mobile development offers multiple paths: native iOS, native Android, or cross-platform frameworks. Each has trade-offs in performance, cost, and time. This guide helps you choose.
Options Overview
Native
- iOS: Swift, Objective-C
- Android: Kotlin, Java
- Platform: Complete access
Cross-Platform
- React Native: JavaScript
- Flutter: Dart
- Xamarin: C#, .NET
Comparison
| Factor | Native | Cross-Platform |
|---|---|---|
| Performance | Best | Good |
| Development speed | Slower | Faster |
| Cost | Higher | Lower |
| Platform access | Full | Limited |
Native iOS
Swift
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("Hello, iOS!")
}
}
}
When to Choose iOS
- High-performance needs
- iOS-only market
- Premium apps
- Apple ecosystem integration
Tools
- Xcode
- SwiftUI / UIKit
- Core Data
- ARKit, HealthKit
Native Android
Kotlin
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
When to Choose Android
- Android-first market
- Custom hardware integration
- Google services
- Open ecosystem
Tools
- Android Studio
- Jetpack Compose
- Kotlin
- Firebase
React Native
JavaScript + Native
import React from 'react';
import { Text, View } from 'react-native';
const App = () => {
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<Text>Hello React Native!</Text>
</View>
);
};
Pros
- JavaScript knowledge
- Large community
- Code sharing
- Fast development
Cons
- Performance overhead
- Native modules needed
- Debugging challenges
- UI consistency
When to Choose
- Team knows JavaScript
- Budget constraints
- Faster time to market
- Simple UI apps
Flutter
Dart
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Flutter')),
body: Center(child: Text('Hello Flutter!')),
),
),
);
}
Pros
- Excellent performance
- Beautiful UI
- Fast development
- Great tooling
Cons
- Dart language
- Smaller community
- Larger app size
- Platform-specific feel
When to Choose
- Performance important
- Custom UI
- Rapid development
- Code sharing needed
Decision Factors
Consider
- Target audience: iOS vs Android vs both
- Team skills: Existing expertise
- Budget: Cost of development
- Timeline: Speed to market
- Performance: Required for your app
Choose Native When
- Gaming, AR, complex graphics
- Deep platform features
- Maximum performance
- Long-term project
Choose Cross-Platform When
- Limited budget
- Faster development
- Simple to moderate UI
- Both platforms needed
Architecture
MVVM
View (UI) ←→ ViewModel (Logic) ←→ Model (Data)
Clean Architecture
Presentation → Domain → Data
State Management
React Native
- useState, useContext
- Redux
- MobX
Flutter
- Provider
- Riverpod
- Bloc
Testing
Native
- XCTest (iOS)
- Espresso (Android)
Cross-Platform
- Jest (React Native)
- Flutter Test
Deployment
App Store
- Apple App Store
- Google Play Store
Publishing
- Certificates, provisioning
- App signing
- Review process
- Update releases
Detailed Framework Comparison
The choice between development approaches depends on comparing specific attributes across native and cross-platform options.
| Attribute | Swift/SwiftUI | Kotlin/Jetpack Compose | Flutter | React Native | Kotlin Multiplatform |
|---|---|---|---|---|---|
| Language | Swift | Kotlin | Dart | JavaScript/TS | Kotlin + platform |
| UI Framework | SwiftUI | Jetpack Compose | Flutter Widgets | React Native Views | Compose Multiplatform |
| Release | 2014/2019 | 2016/2021 | 2017 | 2015 | 2022 (1.0) |
| Code Sharing | 0% (iOS only) | 0% (Android only) | ~95% | ~85% | ~60% shared logic |
| Startup Time | ~300ms | ~350ms | ~500ms | ~800ms | ~350ms |
| Frame Rate | 60/120fps | 60/120fps | 60/120fps | 60fps (JS bridge) | 60/120fps |
| Binary Size | ~8MB (min) | ~4MB (min) | ~15MB (min) | ~10MB (min) | ~5MB (min) |
| Platform Access | Full native | Full native | Plugin bridge | Native Modules | Full native |
| Dev Speed | Medium | Medium | Fast | Fast | Medium |
| Maturity | Very High | High | High | Very High | Maturing |
Performance Benchmarks
Startup time and frame rate consistency remain critical factors for production applications. Independent benchmarks from 2025-2026 reveal significant differences.
Startup Time (cold start, middle-range device)
| Approach | iOS (iPhone 14) | Android (Pixel 7) |
|---|---|---|
| Native | 280-350ms | 320-400ms |
| Flutter | 480-600ms | 450-550ms |
| React Native | 750-900ms | 800-1100ms |
| Kotlin Multiplatform | 300-380ms | 340-420ms |
Memory Usage (medium-complexity app)
| Approach | iOS | Android |
|---|---|---|
| Native | 80-120MB | 100-150MB |
| Flutter | 120-180MB | 110-170MB |
| React Native | 150-220MB | 170-260MB |
| Kotlin Multiplatform | 90-130MB | 100-155MB |
Frame Rate Consistency (scroll-heavy UI, % of frames at 60fps)
| Approach | iOS | Android |
|---|---|---|
| Native | 99.8% | 99.5% |
| Flutter | 99.2% | 99.0% |
| React Native | 95.0% | 92.0% |
| Kotlin Multiplatform | 99.5% | 99.2% |
Code Sharing Analysis
Different cross-platform approaches achieve varying levels of code reuse.
Flutter: ~95% code sharing across platforms. UI is entirely custom-drawn using Skia, so the same Dart code renders identical experiences on both platforms. Platform-specific code typically handles camera, sensors, file system, and native payments.
React Native: ~85% code sharing. Business logic and state management are fully shared. Platform-specific UI adjustments for navigation patterns, safe areas, and platform conventions require separate implementations.
Kotlin Multiplatform: ~60% shared business logic, 0% shared UI (unless using Compose Multiplatform). Shared code covers networking, data models, validation, and repository layers. UI remains fully native (SwiftUI on iOS, Jetpack Compose on Android).
Build and Deploy Workflows
Native iOS
# Build archive for App Store
xcodebuild -workspace App.xcworkspace -scheme App \
-archivePath builds/App.xcarchive archive
# Export for App Store submission
xcodebuild -exportArchive -archivePath builds/App.xcarchive \
-exportPath builds/ -exportOptionsPlist ExportOptions.plist
# Validate and upload
xcrun altool --validate-app -f builds/App.ipa \
--apiKey KEY_ID --apiIssuer ISSUER_ID
Native Android
# Build release AAB
./gradlew bundleRelease
# Sign with upload key
jarsigner -keystore upload-keystore.jks \
app/build/outputs/bundle/release/app-release.aab upload
# Upload via bundletool or Google Play Console
bundletool build-apks --bundle=app-release.aab \
--output=app.apks --ks=upload-keystore.jks
Flutter
# iOS
flutter build ipa --release --export-method app-store
# Android
flutter build appbundle --release
# Both platforms
flutter build ios-framework --output=build/frameworks
React Native
# iOS
npx react-native build-ios --mode release
# Android
cd android && ./gradlew bundleRelease
# Using EAS Build
eas build --platform all --profile production
App Store and Play Store Submission Differences
Apple App Store
- App Review takes 24-48 hours typically
- Requires Apple Developer account ($99/year), certificates, and provisioning profiles
- Review guidelines forbid private API usage, misleading metadata, and crash-prone builds
- TestFlight enables beta testing with up to 10,000 external testers
- App Store Connect manages pricing, territories, and in-app purchases
- Review process includes binary analysis, UI automation tests, and guideline compliance check
Google Play Store
- Review takes 2-24 hours typically, sometimes instant for minor updates
- Requires Google Play Developer account ($25 one-time) and an app signing key
- Policy enforcement covers data safety forms, SDK requirements, and API level targeting
- Closed, Open, and Internal test tracks with staged rollouts up to 100% of users
- Play Console manages pricing, countries, and store listing experiments
- Target API level requirements: new apps must target the latest API level within one year of release
Team Skills Matrix
| Skill Area | Native iOS | Native Android | Flutter | React Native | KMP |
|---|---|---|---|---|---|
| Core Language | Swift | Kotlin | Dart | JavaScript/TS | Kotlin |
| UI Framework | SwiftUI/UIKit | Jetpack Compose | Flutter Widgets | RN Components | Platform-native |
| State Management | Combine/Redux | StateFlow/MVVM | Riverpod/Bloc | Redux/MobX | Platform-native |
| Async/Rx | async/await | Coroutines/Flow | Streams | Promises/async | Coroutines/Flow |
| Navigation | NavigationStack | Jetpack Navigation | GoRouter | React Navigation | Platform-native |
| Local Storage | CoreData/GRDB | Room | Hive/SQLite | AsyncStorage/Realm | Room/CoreData |
| CI/CD | Xcode Cloud/Fastlane | Firebase App Dist. | Codemagic/Fastlane | EAS Build/Fastlane | Custom (Gradle) |
| Testing | XCTest | JUnit/Espresso | Flutter Test | Jest/Detox | JUnit/XCTest |
| Analytics | Firebase/Telemetry | Firebase/Analytics | Firebase/Mixpanel | Firebase/Amplitude | Firebase |
Cost Comparison (Total Cost of Ownership, 2-year Estimate)
| Factor | Native (iOS + Android) | Flutter | React Native | Kotlin Multiplatform |
|---|---|---|---|---|
| Initial Development | 2 separate app teams | 1 shared team | 1 shared team | 2 teams (shared logic) |
| Development Cost | $200K-$400K | $120K-$220K | $100K-$200K | $160K-$280K |
| Maintenance (yearly) | $60K-$100K | $35K-$60K | $30K-$55K | $45K-$75K |
| Team Availability | Abundant | Growing | Very Abundant | Limited |
| Time to Market | 6-12 months | 4-8 months | 3-6 months | 5-10 months |
| Platform Parity Effort | N/A (separate) | Low | Medium | Medium-High |
| Bug Fix Velocity | Separate per platform | Single codebase | Single codebase | Shared logic, separate UI |
Conclusion
Choose based on your specific needs. Native offers best performance but costs more. Cross-platform balances speed and cost. Consider team skills and long-term maintenance.
Comments