iOS Swift Development Overview
Build high-performance native iOS applications using Swift with modern frameworks including SwiftUI, Combine, and async/await patterns.
When to Use Creating native iOS applications with optimal performance Leveraging iOS-specific features and APIs Building apps that require tight hardware integration Using SwiftUI for declarative UI development Implementing complex animations and transitions Instructions 1. MVVM Architecture Setup import Foundation import Combine
struct User: Codable, Identifiable { let id: UUID var name: String var email: String }
class UserViewModel: ObservableObject { @Published var user: User? @Published var isLoading = false @Published var errorMessage: String?
private let networkService: NetworkService
init(networkService: NetworkService = .shared) { self.networkService = networkService }
@MainActor func fetchUser(id: UUID) async { isLoading = true errorMessage = nil
do {
user = try await networkService.fetch(User.self, from: "/users/\(id)")
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}
@MainActor func updateUser(_ userData: User) async { guard let user = user else { return }
do {
self.user = try await networkService.put(
User.self,
to: "/users/\(user.id)",
body: userData
)
} catch {
errorMessage = "Failed to update user"
}
}
func logout() { user = nil errorMessage = nil } }
- Network Service with URLSession class NetworkService { static let shared = NetworkService()
private let session: URLSession private let baseURL: URL
init( session: URLSession = .shared, baseURL: URL = URL(string: "https://api.example.com")! ) { self.session = session self.baseURL = baseURL }
func fetch
let (data, response) = try await session.data(for: request)
try validateResponse(response)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return try decoder.decode(T.self, from: data)
}
func put
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
request.httpBody = try encoder.encode(body)
let (data, response) = try await session.data(for: request)
try validateResponse(response)
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
}
private func validateResponse(_ response: URLResponse) throws { guard let httpResponse = response as? HTTPURLResponse else { throw NetworkError.invalidResponse }
switch httpResponse.statusCode {
case 200...299:
return
case 401:
throw NetworkError.unauthorized
case 500...599:
throw NetworkError.serverError
default:
throw NetworkError.unknown
}
} }
enum NetworkError: LocalizedError { case invalidResponse case unauthorized case serverError case unknown
var errorDescription: String? { switch self { case .invalidResponse: return "Invalid response" case .unauthorized: return "Unauthorized" case .serverError: return "Server error" case .unknown: return "Unknown error" } } }
extension URLRequest { mutating func addAuthHeader() { if let token = KeychainManager.shared.getToken() { setValue("Bearer (token)", forHTTPHeaderField: "Authorization") } } }
- SwiftUI Views struct ContentView: View { @StateObject var userViewModel = UserViewModel()
var body: some View { TabView { HomeView() .tabItem { Label("Home", systemImage: "house") }
ProfileView(viewModel: userViewModel)
.tabItem { Label("Profile", systemImage: "person") }
}
} }
struct HomeView: View { @State var items: [Item] = [] @State var loading = true
var body: some View { NavigationView { ZStack { if loading { ProgressView() } else { List(items) { item in NavigationLink(destination: ItemDetailView(item: item)) { VStack(alignment: .leading) { Text(item.title).font(.headline) Text(item.description).font(.subheadline).foregroundColor(.gray) } } } } } .navigationTitle("Items") .task { await loadItems() } } }
private func loadItems() async { do { items = try await NetworkService.shared.fetch([Item].self, from: "/items") } catch { print("Error: (error)") } loading = false } }
struct ItemDetailView: View { let item: Item @Environment(.dismiss) var dismiss
var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { Text(item.title).font(.title2).fontWeight(.bold) Text(item.description).font(.body) Text("Price: $(String(format: "%.2f", item.price))") .font(.headline).foregroundColor(.blue) Spacer() } .padding() } .navigationBarTitleDisplayMode(.inline) } }
struct ProfileView: View { @ObservedObject var viewModel: UserViewModel @State var isLoading = true
var body: some View { NavigationView { ZStack { if viewModel.isLoading { ProgressView() } else if let user = viewModel.user { VStack(spacing: 20) { Text(user.name).font(.title).fontWeight(.bold) Text(user.email).font(.subheadline) Button("Logout") { viewModel.logout() } .foregroundColor(.red) Spacer() } .padding() } else { Text("No profile data") } } .navigationTitle("Profile") .task { await viewModel.fetchUser(id: UUID()) } } } }
struct Item: Codable, Identifiable { let id: String let title: String let description: String let price: Double }
Best Practices ✅ DO Use SwiftUI for modern UI development Implement MVVM architecture Use async/await patterns Store sensitive data in Keychain Handle errors gracefully Use @StateObject for ViewModels Validate API responses properly Implement Core Data for persistence Test on multiple iOS versions Use dependency injection Follow Swift style guidelines ❌ DON'T Store tokens in UserDefaults Make network calls on main thread Use deprecated UIKit patterns Ignore memory leaks Skip error handling Use force unwrapping (!) Store passwords in code Ignore accessibility Deploy untested code Use hardcoded API URLs