원클릭으로
swiftui-architecture
Architecture patterns for SwiftUI applications including MVVM, navigation, dependency injection, and the @Observable macro
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Architecture patterns for SwiftUI applications including MVVM, navigation, dependency injection, and the @Observable macro
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Strategic search planning for agent-driven research. Generates structured search-term matrices with tiered fallback strategies, engine-specific operators, and grading criteria before executing any searches. Use this skill whenever research requires more than a single search query — comparing technologies, verifying claims across sources, surveying a landscape, investigating a multi-faceted question, or building evidence for a decision. Do NOT use for quick factual lookups, fetching a single known URL, or questions answerable from a single source. Covers tech, academic, regulatory, and general domains. Think of it as "research planning" — the matrix is the plan, execution comes after.
Create language conversion skills for translating code from language A to language B. Use when building 'convert-X-Y' skills, designing type mappings between languages, establishing idiom translation patterns, or defining conversion methodologies. Provides foundational patterns that specific conversion skills extend.
Guide for translating code between programming languages. Use when converting code from one language to another, planning language migrations, understanding conversion challenges, asking about type mappings, idiom translations, or referencing pattern mappings. Covers APTV workflow, type systems, error handling, concurrency, and language-specific gotchas.
Identify skill coverage gaps and improvement opportunities. Use when analyzing missing skills for a task, creating skill gap issues, evaluating skill effectiveness, or refining skill progressive disclosure.
Validate Claude Code skills against best practices. Use when checking skill quality, running validation, or creating improvement issues.
{{DESCRIPTION}}
| name | swiftui-architecture |
| description | Architecture patterns for SwiftUI applications including MVVM, navigation, dependency injection, and the @Observable macro |
| tags | ["swift","swiftui","architecture","mvvm","navigation","dependency-injection"] |
Architecture patterns for SwiftUI applications including MVVM, navigation, dependency injection, and the @Observable macro.
import SwiftUI
// ViewModel using @Observable macro (iOS 17+/macOS 14+)
@Observable
final class ContentViewModel {
var items: [Item] = []
var isLoading = false
var errorMessage: String?
private let repository: ItemRepository
init(repository: ItemRepository = .live) {
self.repository = repository
}
func loadItems() async {
isLoading = true
defer { isLoading = false }
do {
items = try await repository.fetchAll()
} catch {
errorMessage = error.localizedDescription
}
}
}
// View
struct ContentView: View {
@State private var viewModel = ContentViewModel()
var body: some View {
List(viewModel.items) { item in
ItemRow(item: item)
}
.overlay {
if viewModel.isLoading {
ProgressView()
}
}
.task {
await viewModel.loadItems()
}
}
}
// Protocol-based dependency
protocol ItemRepository: Sendable {
func fetchAll() async throws -> [Item]
func save(_ item: Item) async throws
}
// Live implementation
struct LiveItemRepository: ItemRepository {
func fetchAll() async throws -> [Item] {
// Real implementation
}
func save(_ item: Item) async throws {
// Real implementation
}
}
// Mock for testing
struct MockItemRepository: ItemRepository {
var items: [Item] = []
var shouldFail = false
func fetchAll() async throws -> [Item] {
if shouldFail { throw TestError.fetchFailed }
return items
}
func save(_ item: Item) async throws {
// Mock save
}
}
// Static factory pattern
extension ItemRepository where Self == LiveItemRepository {
static var live: LiveItemRepository { LiveItemRepository() }
}
extension ItemRepository where Self == MockItemRepository {
static var mock: MockItemRepository { MockItemRepository() }
}
// Type-safe navigation paths
enum NavigationDestination: Hashable {
case detail(Item)
case settings
case profile(userId: String)
}
struct RootView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
ContentView(path: $path)
.navigationDestination(for: NavigationDestination.self) { destination in
switch destination {
case .detail(let item):
ItemDetailView(item: item)
case .settings:
SettingsView()
case .profile(let userId):
ProfileView(userId: userId)
}
}
}
}
}
// Environment key for repository
private struct ItemRepositoryKey: EnvironmentKey {
static let defaultValue: any ItemRepository = LiveItemRepository()
}
extension EnvironmentValues {
var itemRepository: any ItemRepository {
get { self[ItemRepositoryKey.self] }
set { self[ItemRepositoryKey.self] = newValue }
}
}
// Usage in view
struct ItemListView: View {
@Environment(\.itemRepository) private var repository
@State private var items: [Item] = []
var body: some View {
List(items) { item in
Text(item.name)
}
.task {
items = try? await repository.fetchAll() ?? []
}
}
}
// Preview with mock
#Preview {
ItemListView()
.environment(\.itemRepository, MockItemRepository(items: .preview))
}
MyApp/
├── App/
│ ├── MyApp.swift # @main entry point
│ ├── AppDelegate.swift # UIKit lifecycle (if needed)
│ └── AppState.swift # Global @Observable state
│
├── Features/ # Feature modules
│ ├── Home/
│ │ ├── Views/
│ │ │ ├── HomeView.swift
│ │ │ └── HomeCard.swift
│ │ ├── ViewModels/
│ │ │ └── HomeViewModel.swift
│ │ └── Models/
│ │ └── HomeItem.swift
│ │
│ ├── Profile/
│ │ ├── Views/
│ │ ├── ViewModels/
│ │ └── Models/
│ │
│ └── Settings/
│ └── ...
│
├── Core/ # Shared infrastructure
│ ├── Repositories/
│ │ └── ItemRepository.swift
│ ├── Services/
│ │ ├── Network/
│ │ │ ├── APIClient.swift
│ │ │ ├── Endpoints.swift
│ │ │ └── NetworkError.swift
│ │ └── Persistence/
│ │ ├── DatabaseManager.swift
│ │ └── KeychainService.swift
│ └── Extensions/
│ ├── View+Extensions.swift
│ └── Date+Extensions.swift
│
├── Shared/ # Reusable UI components
│ ├── Components/
│ │ ├── LoadingView.swift
│ │ ├── ErrorView.swift
│ │ └── AsyncButton.swift
│ ├── Modifiers/
│ │ ├── CardStyle.swift
│ │ └── ShimmerEffect.swift
│ └── Styles/
│ └── ButtonStyles.swift
│
├── Utilities/ # Helpers and constants
│ ├── Constants.swift
│ ├── Logger.swift
│ └── Formatters.swift
│
├── Resources/
│ ├── Assets.xcassets # Images and colors
│ ├── Localizable.xcstrings # Localized strings (Xcode 15+)
│ └── Fonts/ # Custom fonts
│ └── CustomFont.ttf
│
└── Tests/
├── UnitTests/
│ ├── ViewModels/
│ │ └── HomeViewModelTests.swift
│ └── Services/
│ └── APIClientTests.swift
└── UITests/
├── HomeUITests.swift
└── Helpers/
└── XCUIApplication+Extensions.swift
MyAppPackage/
├── Package.swift
├── Sources/
│ ├── MyApp/ # Main app target
│ │ └── MyApp.swift
│ ├── Features/ # Feature library
│ │ ├── Home/
│ │ └── Profile/
│ ├── Core/ # Core library
│ │ ├── Networking/
│ │ └── Persistence/
│ └── SharedUI/ # UI components library
│ ├── Components/
│ └── Modifiers/
└── Tests/
├── CoreTests/
└── FeaturesTests/