Ios architecture
Skill almasumdev/awesome-ios-agent-skills/.github/skills/architecture/ios-architecture
Curated agent skills, conventions, and workflows for building iOS apps (Swift, SwiftUI, UIKit) with AI coding agents.
npx -y skills add almasumdev/awesome-ios-agent-skills --skill ios-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Expert guidance on modern iOS application architecture using Clean Architecture, SwiftUI-first layering, and Swift Package Manager (SPM) feature modularization. Use this when asked about project structure, module graph, or DI.
SKILL.md
5.2 KB, as published. Nobody here has run it
iOS Modern Architecture & Modularization
Instructions
When designing or refactoring an iOS application, follow Clean Architecture principles. Dependencies flow inward toward pure Swift domain code.
1. High-Level Layers
- Presentation Layer
- Responsibility: Rendering views and handling user intent.
- Components:
View,@Observablemodels (Observation framework), TCAReducers, coordinators. - Dependencies: Domain layer (
UseCases or repository protocols) only.
- Domain Layer (Pure Swift)
- Responsibility: Business rules and entities.
- Components: Value-type entities,
UseCaseprotocols, repository protocols. - Rule: Must not import
UIKit,SwiftUI, or persistence frameworks. Ship as its own SPM package for enforcement.
- Data Layer
- Responsibility: Fetching, caching, persisting data.
- Components: Repository implementations, remote clients (
URLSession), local stores (SwiftData/Core Data), DTOs + mappers.
2. Architectural Styles
| Style | When to pick it |
|---|---|
| MV | Small/medium SwiftUI apps. View binds directly to an @Observable model. |
| MVVM | Teams migrating from UIKit; explicit ViewModel boundary and testability focus. |
| TCA | Large apps needing exhaustive testing, time-travel debugging, strict effects. |
Pick one per app and stay consistent. Mixing styles is acceptable at the feature module boundary, not inside a feature.
3. Dependency Injection
Use initializer injection with protocol abstractions. For SwiftUI, expose shared dependencies through @Environment values or a lightweight container. Avoid @EnvironmentObject for pure service graphs — prefer constructors.
protocol ArticleRepository: Sendable {
func latest() async throws -> [Article]
}
@Observable
final class ArticleListModel {
private let repository: any ArticleRepository
var articles: [Article] = []
var error: Error?
init(repository: any ArticleRepository) {
self.repository = repository
}
@MainActor
func load() async {
do { articles = try await repository.latest() }
catch { self.error = error }
}
}
An environment key for cross-cutting services:
private struct AnalyticsKey: EnvironmentKey {
static let defaultValue: any Analytics = NoopAnalytics()
}
extension EnvironmentValues {
var analytics: any Analytics {
get { self[AnalyticsKey.self] }
set { self[AnalyticsKey.self] = newValue }
}
}
4. Modularization with SPM
Split the app into small SPM packages. A workable layout:
MyApp/
├── MyApp.xcodeproj # Thin shell target
├── App/ # Composition root, @main
├── Packages/
│ ├── Core/ # Logging, Env, shared types
│ ├── DesignSystem/ # Tokens, shared SwiftUI components
│ ├── Domain/ # Pure Swift entities + protocols
│ ├── Data/ # Repository implementations
│ └── Features/
│ ├── Articles/
│ │ ├── ArticlesDomain/
│ │ ├── ArticlesData/
│ │ └── ArticlesUI/
│ └── Profile/
└── Package.swift # Root manifest when using a single package
Example Package.swift slice:
// swift-tools-version: 5.10
import PackageDescription
let package = Package(
name: "Articles",
platforms: [.iOS(.v15)],
products: [
.library(name: "ArticlesUI", targets: ["ArticlesUI"])
],
dependencies: [
.package(path: "../Domain"),
.package(path: "../DesignSystem")
],
targets: [
.target(name: "ArticlesDomain"),
.target(name: "ArticlesData", dependencies: ["ArticlesDomain"]),
.target(name: "ArticlesUI", dependencies: ["ArticlesDomain", "DesignSystem"]),
.testTarget(name: "ArticlesDomainTests", dependencies: ["ArticlesDomain"])
]
)
5. Composition Root
Assemble real implementations in the @main App only. Features depend on protocols:
@main
struct MyApp: App {
private let container = AppContainer.live()
var body: some Scene {
WindowGroup {
RootView()
.environment(container.articlesModel)
.environment(\.analytics, container.analytics)
}
}
}
Checklist
- Domain package has no
UIKit/SwiftUI/ persistence imports. - Repositories expose domain entities only — never DTOs.
- One architecture style per app; features do not import siblings directly.
- Composition happens in the app target; features depend on protocols.
- Each feature module ships with its own test target.