# mobile-skills > Master iOS development with Swift, Android development with Kotlin, React Native, Flutter, and cross-platform mobile technologies. - Author: pluginagentmarketplace - Repository: pluginagentmarketplace/custom-plugin-nextjs - Version: 20260105115548 - Stars: 1 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/pluginagentmarketplace/custom-plugin-nextjs - Web: https://mule.run/skillshub/@@pluginagentmarketplace/custom-plugin-nextjs~mobile-skills:20260105115548 --- --- name: mobile-skills description: Master iOS development with Swift, Android development with Kotlin, React Native, Flutter, and cross-platform mobile technologies. sasmp_version: "1.3.0" skill_type: atomic version: "2.0.0" parameters: platform: type: string enum: [ios, android, cross-platform] default: cross-platform framework: type: string enum: [swift, kotlin, react-native, flutter] default: react-native validation_rules: - pattern: "^[A-Z][a-zA-Z0-9]*$" target: component_names message: Components must be PascalCase - pattern: ".*\\.bundle$" target: ios_bundle_id message: Bundle ID must end with domain retry_config: max_attempts: 3 backoff: exponential initial_delay_ms: 500 logging: on_entry: "[Mobile] Starting: {task}" on_success: "[Mobile] Completed: {task}" on_error: "[Mobile] Failed: {task} - {error}" dependencies: agents: - mobile-developer --- # Mobile Development Skills ## iOS Development (Swift) ```swift import SwiftUI struct ContentView: View { @State private var count = 0 @State private var isLoading = false @State private var error: Error? var body: some View { VStack { if isLoading { ProgressView() } else if let error = error { ErrorView(error: error, retry: loadData) } else { Text("Count: \(count)") .font(.headline) Button(action: { count += 1 }) { Text("Increment") } } } .task { await loadData() } } func loadData() async { isLoading = true defer { isLoading = false } do { // Fetch data } catch { self.error = error } } } // MVVM Pattern with Error Handling @MainActor class ViewModel: ObservableObject { @Published var items: [Item] = [] @Published var error: Error? @Published var isLoading = false func fetchItems() async { isLoading = true defer { isLoading = false } do { items = try await APIService.getItems() } catch { self.error = error } } } ``` ## Android Development (Kotlin) ```kotlin import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun CounterApp(viewModel: CounterViewModel = viewModel()) { val uiState by viewModel.uiState.collectAsState() Scaffold( topBar = { TopAppBar(title = { Text("Counter") }) } ) { padding -> Box(modifier = Modifier.padding(padding)) { when (val state = uiState) { is UiState.Loading -> CircularProgressIndicator() is UiState.Error -> ErrorMessage(state.message) is UiState.Success -> { Button(onClick = { viewModel.increment() }) { Text("Count: ${state.count}") } } } } } } // ViewModel with sealed class state class CounterViewModel : ViewModel() { private val _uiState = MutableStateFlow(UiState.Loading) val uiState: StateFlow = _uiState.asStateFlow() sealed class UiState { object Loading : UiState() data class Success(val count: Int) : UiState() data class Error(val message: String) : UiState() } } ``` ## React Native with Error Boundaries ```javascript import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, Button, ActivityIndicator } from 'react-native'; export default function App() { const [count, setCount] = useState(0); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const fetchData = useCallback(async () => { setLoading(true); setError(null); try { const response = await fetch('https://api.example.com/data'); if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); setCount(data.count); } catch (err) { setError(err.message); } finally { setLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); if (loading) return ; if (error) return ; return ( Count: {count}