iOS — Swift
Standar pengembangan aplikasi iOS menggunakan Swift dan SwiftUI sebagai pendekatan utama.
Tech Stack
| Kategori | Library / Tool | Versi Min. |
|---|---|---|
| Language | Swift | 6.0+ (strict concurrency) |
| Min Deployment | iOS 16.0 | — |
| UI Framework | SwiftUI (utama) + UIKit (legacy) | — |
| Build System | Xcode + SPM (Swift Package Manager) | 16+ |
| Navigation | NavigationStack (SwiftUI) | — |
| DI | Factory / swift-dependencies | Latest |
| Networking | URLSession + async/await | — |
| Serialization | Codable (native) | — |
| Image Loading | Kingfisher / SDWebImage | Latest |
| Local DB | SwiftData / Core Data | — |
| State Management | @Observable (Observation framework) | — |
| Testing | XCTest, Swift Testing | — |
| CI/CD | Fastlane + GitLab CI | — |
Swift 6 strict concurrency
Swift 6 mengaktifkan data race safety secara default — kode yang menyentuh state dari luar @MainActor tanpa proteksi (actor, Sendable) akan gagal compile, bukan cuma warning. Migrasi project lama sebaiknya bertahap: aktifkan SWIFT_STRICT_CONCURRENCY per-modul dulu, bukan langsung project-wide.
Project Structure
AppName/
├── App/
│ ├── AppNameApp.swift # @main entry point
│ └── ContentView.swift
├── Data/
│ ├── Remote/ # API services & DTOs
│ ├── Local/ # SwiftData models / persistence
│ └── Repository/ # Repository implementations
├── Domain/
│ ├── Models/ # Domain models
│ ├── Repositories/ # Repository protocols
│ └── UseCases/ # Use cases
├── Presentation/
│ ├── Screens/ # SwiftUI views (per screen)
│ │ ├── Home/
│ │ │ ├── HomeView.swift
│ │ │ └── HomeViewModel.swift
│ │ └── Profile/
│ ├── Components/ # Reusable UI components
│ └── Navigation/ # Navigation coordinator
├── Core/
│ ├── Extensions/
│ ├── Utilities/
│ └── Constants/
├── Resources/
│ ├── Assets.xcassets
│ └── Localizable.xcstrings
└── Tests/
├── UnitTests/
└── UITests/
Coding Standards
Swift Style Guide
- Ikuti Swift API Design Guidelines.
- Gunakan
SwiftLintsebagai linter. - Maksimum line length: 120 karakter.
SwiftUI Best Practices
// ✅ Good - View terpisah dari logic
struct UserCardView: View {
let user: UserModel
let onTap: () -> Void
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(user.name)
.font(.headline)
Text(user.email)
.font(.subheadline)
.foregroundStyle(.secondary)
}
.padding()
.onTapGesture(perform: onTap)
}
}
// ❌ Bad - Fetching data langsung di View
struct UserCardView: View {
var body: some View {
// Jangan fetch data di sini!
let user = APIService.shared.getUser()
Text(user.name)
}
}
ViewModel Pattern (Observation Framework)
@MainActor // wajib di Swift 6 strict concurrency — ViewModel selalu diakses dari SwiftUI (main actor)
@Observable
final class UserViewModel {
private let getUserUseCase: GetUserUseCaseProtocol
var uiState: UserUiState = .idle
init(getUserUseCase: GetUserUseCaseProtocol) {
self.getUserUseCase = getUserUseCase
}
func loadUser(id: String) async {
uiState = .loading
do {
let user = try await getUserUseCase.execute(id: id)
uiState = .success(user)
} catch {
uiState = .error(error.localizedDescription)
}
}
}
enum UserUiState {
case idle
case loading
case success(User)
case error(String)
}
Build & Run
# Build via command line
xcodebuild -scheme AppName -sdk iphonesimulator build
# Run unit tests
xcodebuild test -scheme AppName -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17'
# Run SwiftLint
swiftlint lint --strict
# Archive for distribution
xcodebuild archive -scheme AppName -archivePath build/AppName.xcarchive
Swift Package Manager
Gunakan SPM sebagai dependency manager utama. CocoaPods hanya digunakan jika library tertentu tidak support SPM.