StressPunch is a small SwiftUI app designed as a lighthearted way to create and manage custom stress targets, choose favorites, and interact with them through a simple punch animation and sound effect.
The project is presented as a portfolio sample demonstrating modern iOS development with SwiftUI, SwiftData, PhotosUI, Apple’s Observation framework, AVFAudio, and automated testing with Swift Testing.
- Create custom stress targets
- Select images from the user's photo library
- Edit existing targets
- Delete targets
- Mark up to four targets as favorites
- Restore built-in default targets
- Persist target data with SwiftData
- Remember the currently selected target
- Display a punch graphic at the user's tap location
- Animate the selected target when tapped
- Play an accompanying sound effect
- Manage targets through a dedicated library interface
- Swift
- SwiftUI
- SwiftData
- Swift Testing
- PhotosUI
- Observation
- AVFAudio
- Xcode
- Git
StressPunch uses a lightweight MVVM-style structure appropriate for the size of the project.
StressTarget is a SwiftData model representing an individual stress target.
Each target stores:
- Name
- Message
- Selection state
- Favorite state
- A built-in image name or user-selected image data
SwiftData provides persistence for both built-in and user-created targets.
The primary views are:
StressPunchView— main interaction screenMoreStressTargetsView— browse and select targetsManageTargetLibraryView— manage favorites, editing, deletion, and default restorationAddEditTargetView— create and edit custom targets
StressPunchViewModel coordinates interaction-specific behavior including:
- Audio playback
- Temporary punch-overlay presentation
- Punch animation behavior
SwiftUI and SwiftData manage most application state directly where appropriate, keeping the architecture intentionally lightweight rather than introducing abstractions that are unnecessary for the size of the project.
Small business rules are kept separate from presentation code where appropriate so they can be tested independently.
For example, favorite-selection logic is handled by a pure function that determines whether another target can be favorited based on the current favorite count and the target’s current state.
StressPunch uses SwiftData to persist target information.
User-selected images are stored as Data using external storage:
@Attribute(.externalStorage) var imageData: Data?Built-in targets reference images stored in the asset catalog instead of duplicating image data in the persistent store.
When the app launches without stored targets, the default target collection is inserted into the SwiftData model context.
Users can create a custom stress target by selecting an image through PhotosPicker.
The selected image is loaded asynchronously and stored with its corresponding StressTarget.
Users may choose up to four favorite targets.
Favorites are displayed directly on the main screen for quick access, while the complete collection remains available in the target library.
The favorite-limit rule is separated from the SwiftUI presentation layer and covered by unit tests, including boundary conditions for adding and removing favorites.
StressPunch includes automated tests using Swift Testing.
Unit tests verify the favorite-selection business rule independently from SwiftUI and SwiftData.
The tests cover:
- Favoriting when no favorites exist
- Favoriting when below the four-target limit
- Preventing an additional favorite when four favorites already exist
- Keeping an existing favorite enabled so it can still be unfavorited
Integration tests use an in-memory SwiftData container to verify persistence behavior without modifying production data.
The tests cover:
- Creating and saving a
StressTarget - Fetching a saved target
- Updating and persisting target values
- Deleting a target from the persistent store
Using an in-memory container keeps each persistence test isolated and repeatable.
StressPunch demonstrates:
- Building an iOS interface with SwiftUI
- Persistent models with SwiftData
- State ownership and bindings
- SwiftUI navigation and sheet presentation
- CRUD-style data management
- Photo selection with PhotosUI
- Asynchronous image loading
- Rendering user-provided images
- Audio playback with
AVAudioPlayer - Custom tap interactions and animation
- Optional handling without unnecessary force unwrapping
- Maintaining a single source of truth for persistent data
- Separating testable business logic from presentation behavior
- Unit testing with Swift Testing
- SwiftData integration testing with an in-memory model container
- Refactoring and modernizing an existing codebase
StressPunch originated as an earlier iOS learning project and was later redesigned and refactored as a public portfolio sample.
The refactor focused on:
- Renaming and rebranding the original project
- Removing unnecessary force unwraps
- Improving optional handling
- Simplifying state ownership
- Using SwiftData queries as the primary source of truth
- Removing duplicated application state
- Improving persistence error handling
- Cleaning up naming and project structure
- Separating persistent data from UI-specific behavior
- Extracting business logic where independent testing adds value
- Adding automated unit and persistence integration tests
- Preparing the codebase for public review
This project represents the process of revisiting earlier code, identifying weaknesses, and improving it using knowledge gained through subsequent iOS development experience.
- Xcode 16 or later
- iOS 17 or later
- Swift 5.9 or later
- Clone the repository:
git clone https://github.com/Brett-Buchholz/StressPunch.git-
Open
StressPunch.xcodeprojin Xcode. -
Select an iPhone simulator or connected iOS device.
-
Build and run the project.
No external packages, accounts, or API keys are required.
Run the full automated test suite in Xcode with:
Command-U
or choose:
Product → Test
The test suite includes both pure unit tests and SwiftData integration tests.
Potential future improvements include:
- Additional accessibility improvements
- User-facing persistence error handling
- Additional animation and interaction feedback
- Expanded automated test coverage as new features are added
Brett Buchholz
iOS Developer focused on Swift, SwiftUI, and UIKit.


