- Purpose: Central coordinator that orchestrates all data flow
- Responsibilities:
- Fetches sleep data from Sleep class
- Sends processed data to CuratorAI
- Manages state with @Published properties
- Coordinates between Sleep and CuratorAI
- Handles UI updates through reactive bindings
- Purpose: The only UI component in the app
- Responsibilities:
- Displays sleep data (REM, Deep, Core, Total, Awakenings, Sleep Score)
- Shows AI curator messages
- Handles user interactions
- Uses Manager for all data access
- Purpose: Handles all sleep data processing and HealthKit integration
- Responsibilities:
- Requests HealthKit authorization
- Fetches raw sleep data from HealthKit
- Processes sleep samples (REM, Deep, Core, Awakenings)
- Calculates sleep score
- Returns structured SleepData to Manager
- Purpose: Generates encouraging messages based on sleep data
- Responsibilities:
- Receives processed sleep data from Manager
- Generates AI messages using OpenAI API
- Returns encouraging messages to Manager
- Does NOT fetch data directly
ContentView (UI) → Manager (Controller) → Sleep (data) + CuratorAI (message)
- ContentView requests data from Manager
- Manager calls Sleep class to fetch and process HealthKit data
- Sleep class returns processed
SleepDatato Manager - Manager sends sleep data to CuratorAI for message generation
- CuratorAI returns AI message to Manager
- Manager combines sleep data + AI message
- ContentView displays both sleep data and AI message
- Each class has one clear purpose
- Manager coordinates, Sleep processes data, CuratorAI generates messages, ContentView displays
- Sleep: Only handles HealthKit data processing
- CuratorAI: Only generates AI messages (no data fetching)
- Manager: Only coordinates between components
- ContentView: Only handles UI display
- Only ContentView exists for UI
- No multiple view classes
- All UI logic centralized in one place
- Manager uses @Published properties for reactive UI updates
- ContentView automatically updates when Manager state changes
- Clean data binding between UI and data layer
- Manager conforms to
ObservableObjectfor reactive UI updates - Sleep class handles all HealthKit integration and data processing
- CuratorAI is stateless and only generates messages
- ContentView uses
@StateObjectto observe Manager changes - All data flows through Manager - no direct communication between other classes
Heartifacts/
├── ContentView.swift # Single UI class
├── Manager.swift # Controller/coordinator
├── Sleep.swift # Data model & HealthKit processor
├── CuratorAI.swift # AI message generator
└── HeartifactsApp.swift # App entry point
This architecture ensures clean separation of concerns, single responsibility principle, and maintainable code structure.