Language Introspector
At a glance
| Item | Summary |
|---|---|
| Purpose | Explore locale, language, script, direction, transcription, and localized formatter behavior. |
| Architecture | A SwiftUI navigation shell routes through AppScreen; each feature owns one or more main-actor observable models and passes them to bindable child views. |
| Feature boundary | Models own Foundation calculations and formatter mutation; views own layout and user bindings. |
Project structure
LanguageIntrospector/
├── LanguageIntrospectorApp.swift
├── ContentView.swift
├── AppScreen.swift
├── Languages{Model,View}.swift
├── DatesView.swift
├── *Formatter{Model,View}.swift
├── {Measurements,Names,Numbers}{Model,View}.swift
└── small presentation helpers
Files pair a model with its feature view. The date screen is a composition of four independent formatter model/view pairs.
Overall architecture
flowchart LR
App["LanguageIntrospectorApp"] --> Content["ContentView"]
Content --> Route["AppScreen enum"]
Route --> Languages["LanguagesView + LanguagesModel"]
Route --> Dates["DatesView + four formatter models"]
Route --> Measures["Measurements view/model"]
Route --> Names["Names view/model"]
Route --> Numbers["Numbers view/model"]
Languages --> Foundation["Locale / formatter APIs"]
Dates --> Foundation
Reference code
LanguageIntrospector/AppScreen.swift:36 — the route enum owns the exact mapping from navigation identity to feature composition.
extension AppScreen {
// ...
@MainActor
// ...
}Ownership and state
classDiagram
ContentView *-- AppScreen : navigation selection
LanguagesView *-- LanguagesModel : State
DatesView *-- DateFormatterModel : State
DatesView *-- DateComponentsModel : State
DatesView *-- DateIntervalFormatterModel : State
DatesView *-- RelativeDateTimeFormatterModel : State
DateFormatterView --> DateFormatterModel : Bindable
DateFormatterModel *-- DateFormatter
Ownership evidence
LanguageIntrospector/DatesView.swift:10 — the feature root owns all formatter-model lifetimes and injects them into children.
struct DatesView: View {
// ...
}Feature roots own observable model instances with @State. Child views receive @Bindable access for UI controls. Each model is the mutation authority for its Foundation formatter and derived presentation strings.
Class and protocol design
| Type | Responsibility |
|---|---|
AppScreen |
Stable, codable navigation identity plus label/destination mapping. |
LanguagesModel |
Sort language examples against preferred locales and expose the selection. |
| Formatter model classes | Own formatter objects, inputs, and derived localized output. |
| Feature views | Own model lifetime and compose the screen. |
| Bindable child views | Bind controls to one supplied model without owning it. |
| Small view modifiers/helpers | Reuse presentation without moving feature state. |
The app uses Swift observation and SwiftUI protocols; it defines no service/repository protocol because all data is local and deterministic.
Access control
| Boundary | Effect and rationale |
|---|---|
private @State models and navigation fields |
Makes the feature/root view the explicit lifetime owner. |
private sample data, formatter helpers, and update methods |
Prevents views from bypassing model invariants. |
Model binding properties remain implicit internal |
Child views in separate files can bind within the app module. |
All app types are internal; no public API |
The source builds an executable, not a reusable package. |
@MainActor models |
Constrains observable UI mutation to the main actor; this is isolation, not access control. |
LanguageIntrospector/LanguagesModel.swift:19 shows private sorting logic and LanguageIntrospector/DateFormatterModel.swift:79 shows the private mutation gate.
Logic ownership and placement
| Logic | Owner |
|---|---|
| Navigation identity and destination selection | AppScreen |
| Preferred-language matching and sorting | LanguagesModel |
| Formatter configuration and derived strings | Corresponding formatter model |
| Model lifetime and feature composition | Top-level feature view |
| Reusable styling | View modifiers and presentation helpers |
Design patterns
| Pattern | Evidence | Purpose |
|---|---|---|
| Observable model | LanguageIntrospector/DateFormatterModel.swift:10 |
Moves mutable formatter logic out of view layout. |
| Model-view split | LanguageIntrospector/DateFormatterView.swift:10 |
A bindable view renders and edits a supplied model. |
| Enum router | LanguageIntrospector/AppScreen.swift:10 |
Keeps navigation labels and destinations exhaustive. |
| Feature slicing | LanguageIntrospector/DatesView.swift:10 |
Composes several focused formatter models without one global store. |
Naming conventions
- Model/view pairs share a stem:
DateFormatterModelandDateFormatterView. - Feature aggregation drops the implementation suffix:
DatesViewowns all date-format models. - Derived properties describe output (
localizedDateWithPattern,sortedLanguageTexts) while mutation helpers use verbs (updateFormatter).
Architecture takeaways
- Give each feature root ownership of its observable model lifetime.
- Pass models to children as bindable dependencies rather than reconstructing them.
- Use an enum router for a small, closed navigation catalog.
- Keep deterministic Foundation formatting logic in focused models, not a global service.
Source map
| Source | Role |
|---|---|
LanguageIntrospector/LanguageIntrospectorApp.swift:10 |
Composition root |
LanguageIntrospector/AppScreen.swift:10 |
Navigation router |
LanguageIntrospector/ContentView.swift:10 |
Navigation shell |
LanguageIntrospector/LanguagesModel.swift:11 |
Representative observable model |
LanguageIntrospector/DatesView.swift:10 |
Feature model ownership |
LanguageIntrospector/DateFormatterView.swift:10 |
Bindable child view |