Podcast Download Queue
Build an iOS podcast app in Swift focused on getting the offline experience right. Users subscribe to podcasts by RSS feed URL, add episodes to a download queue, and listen offline. Downloads run in the background with URLSession, so they keep going when the app is closed; they can be paused, resumed and retried, and show their progress. The app remembers where you stopped in every episode. Everything (podcasts, episodes, queue order, download state and playback position) is stored with SwiftData. You'll learn background URLSession downloads, parsing RSS with XMLParser, SwiftData models and queries, managing files on disk, and playing audio with AVFoundation.
- Estimate
- ~15.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
SwiftData · URLSession
Project roadmap
- 01
Model podcasts and episodes
~2hCreate a SwiftUI app with SwiftData models: Podcast (feed URL, title, artwork URL) and Episode (guid, title, audio URL, publish date, duration, download state such as none, queued, downloading, downloaded or failed, local file name, playback position in seconds, and queue position). Set up the model container and a podcast list screen. Done when: podcasts and episodes can be created and listed from sample data.
- 02
Subscribe by RSS feed
~2.5hAdd a screen to paste a feed URL. Download it with URLSession and parse it with XMLParser into the podcast title, artwork and episodes (title, enclosure URL, guid, date and duration). Match episodes by guid so refreshing a feed doesn't create duplicates. Show clear errors for invalid URLs and feeds that aren't RSS. Done when: subscribing to a real podcast feed lists its episodes, and refreshing adds only new ones.
- 03
Build the download queue
~3hCreate a DownloadManager using a background URLSessionConfiguration and download tasks. Queued episodes download at most 2 at a time, in queue order. Update progress from the delegate's didWriteData, and when a download finishes, move the file into the app's Documents folder at once (the temporary file is deleted after the callback) and mark the episode downloaded. Done when: queuing several episodes downloads them in order, 2 at a time, with visible progress.
- 04
Pause, resume, retry and background
~2.5hSupport pausing with cancel(byProducingResumeData:) and resuming from that data. On failure, mark the episode failed with the reason and offer a Retry button. Handle downloads that finish while the app is closed by implementing application(_:handleEventsForBackgroundURLSession:) and recreating the session with the same identifier. Done when: a download paused midway resumes without starting over, and downloads finish while the app is in the background.
- 05
Play and remember positions
~2hPlay downloaded episodes from the local file with AVPlayer (streaming when not downloaded). Save the playback position every few seconds and when pausing, and resume from it next time. Configure the audio session so playback continues with the screen locked, and add skip back 15 seconds and forward 30 seconds. Done when: stopping an episode midway and reopening the app resumes at the same spot.
- 06
Manage the queue and storage
~1.5hAdd a Queue screen where episodes can be reordered by dragging and removed by swiping. Show the storage each downloaded episode uses and the total, with a way to delete a download (removing the file too). Automatically delete downloads of finished episodes, as a setting. Done when: reordering changes the download order, and deleting frees the space.
- 07
Test the logic
~2hWrite unit tests for the RSS parser with sample feed files (including missing fields and duplicate guids), the queue ordering, and the download state changes, using an in-memory SwiftData container. Test by hand in airplane mode that downloaded episodes still play. Done when: the tests pass, and offline playback works.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack