iOS Offline Survey
Build an iOS app for filling in surveys in places without a reliable connection, such as farms, building sites or rural clinics. Survey forms are defined in JSON and downloaded when online; answers are checked on the spot (required fields, number ranges, formats and questions that only appear based on earlier answers) and saved with SwiftData as soon as they're entered. Completed surveys wait in a queue and are uploaded with URLSession when the phone is back online, retried on failure, and never sent twice. You'll learn building forms dynamically in SwiftUI, validation rules, SwiftData, background uploads, idempotent sync, and testing offline behavior.
- Estimate
- ~15h
- Steps
- 6
- Completed by
- 0
- Proposed by
- codeseed.app
SwiftUI · SwiftData · URLSession
Project roadmap
- 01
Design the forms and sync
~2.5hWrite DESIGN.md: the JSON form format (sections and questions of types text, number, single and multiple choice, date and photo; rules such as required, min, max and pattern; and conditions like show only if question 3 is yes), how form versions work, the submission states (draft, queued, uploading, uploaded and rejected), and the upload API with an idempotency key per submission. Done when: DESIGN.md covers the form format, states and sync rules.
- 02
Render forms from JSON
~3hDecode forms with Codable and render them in SwiftUI with the right control for each question type, showing or hiding questions whose conditions change as the user answers. Save answers to a SwiftData draft after every change, so nothing is lost if the app closes. Done when: a sample form renders correctly, conditional questions appear and disappear, and drafts survive restarting.
- 03
Validate answers
~2hWrite the validation as pure Swift functions: required fields (only if the question is visible), number ranges, text patterns and date limits, showing errors next to each question as the user types and summarizing them at the top on submit. Hidden questions' answers are not submitted. Done when: a form can't be submitted with errors, and messages point to the exact question.
- 04
Queue and upload submissions
~3hWhen a form is submitted, mark it queued with a new UUID as its idempotency key. An uploader sends queued submissions one by one with URLSession (photos compressed), marks them uploaded only after the server confirms, retries network errors with increasing waits, and marks rejected ones with the reason for the user to fix. Watch connectivity with NWPathMonitor and upload when online, and also in the background with BGTaskScheduler. Write a small server to receive submissions. Done when: surveys filled offline upload by themselves when online.
- 05
Handle interruptions and form updates
~2hMake sure an upload interrupted after the server saved it is recognized by its idempotency key, not duplicated. Restore submissions stuck in uploading after a crash. When a newer form version is downloaded, keep drafts on their original version. Show pending uploads and the last sync time. Done when: interruptions at any point never duplicate or lose a submission.
- 06
Test it
~2.5hWrite tests: form decoding, condition evaluation and validation rules, SwiftData drafts with an in-memory container, and the uploader against a fake transport that fails, times out, rejects or accepts, including an interruption after the server saved. Test by hand in airplane mode. Done when: all tests pass, and offline filling and later upload work on a device.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack