Lewati ke konten utama

iOS — Swift

Standar pengembangan aplikasi iOS menggunakan Swift dan SwiftUI sebagai pendekatan utama.

Tech Stack​

KategoriLibrary / ToolVersi Min.
LanguageSwift6.0+ (strict concurrency)
Min DeploymentiOS 16.0—
UI FrameworkSwiftUI (utama) + UIKit (legacy)—
Build SystemXcode + SPM (Swift Package Manager)16+
NavigationNavigationStack (SwiftUI)—
DIFactory / swift-dependenciesLatest
NetworkingURLSession + async/await—
SerializationCodable (native)—
Image LoadingKingfisher / SDWebImageLatest
Local DBSwiftData / Core Data—
State Management@Observable (Observation framework)—
TestingXCTest, Swift Testing—
CI/CDFastlane + 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​

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.