Downloads & Offline Access
Relevant source files
The following files were used as context for generating this wiki page:
- Putio/Features/Downloads/DownloadsViewController.swift
- Putio/Common/Helpers/AVDownloadManager.swift
- Putio/Features/Downloads/AudioDownloadManager.swift
- Putio/Features/Downloads/VideoDownloadManager.swift
- Putio/Features/Downloads/DownloadModel.swift
- Putio/Common/Helpers/Realm.swift
- Putio/Features/Downloads/DownloadSupport.swift
- Putio/Features/Downloads/DownloadedFilePresenter.swift
The Downloads & Offline Access system provides the infrastructure for fetching, storing, and managing media files locally on iOS devices. This module allows users to consume content from their put.io account without an active internet connection by leveraging background transfer services and persistent local storage.
The architecture is split into specialized managers for different media types: VideoDownloadManager handles HLS (HTTP Live Streaming) assets for adaptive bitrate playback, while AudioDownloadManager manages standard file downloads. Both utilize URLSession background configurations to ensure transfers continue even when the app is suspended or terminated.
Core Data Model
All download records are persisted in a Realm database using the Download class. This model tracks the lifecycle of a download from initiation to completion or failure.
Download Entity Attributes
| Field | Type | Description |
|---|---|---|
id | Int | Primary key, matching the put.io file ID. |
name | String | The display name of the file. |
stateRaw | Int | Integer representation of Download.State (queued, active, completed, etc.). |
fileTypeRaw | Int | Integer representation of Download.FileType (video, audio). |
progress | String | Percentage completion (e.g., "0.50"). |
size | Int64 | Total size of the file in bytes. |
completedAt | Date? | Timestamp of when the download finished successfully. |
Sources: Putio/Features/Downloads/DownloadModel.swift:6-23, Putio/Features/Downloads/DownloadModel.swift:51-53
The diagram shows the Download Realm object and its associated enumerations for state management and media classification. Sources: Putio/Features/Downloads/DownloadModel.swift:7-13
Download Management Architecture
The system employs separate managers to handle the technical requirements of different file formats. Both managers use background URLSession identifiers to maintain persistence.
Video Download Manager
VideoDownloadManager specializes in HLS content using AVAssetDownloadURLSession. It creates AVAssetDownloadTask objects which allow the system to optimize download strategies for multi-bitrate streams.
- URL Resolving: It fetches remote stream URLs, often appending subtitle keys if available.
- Persistence: Instead of direct file paths, it stores
Databookmarks inUserDefaults. This is necessary because the local location of HLS.movpkgfiles can be moved by the OS.
Sources: Putio/Features/Downloads/VideoDownloadManager.swift:23-41, Putio/Features/Downloads/VideoDownloadManager.swift:68-88, Putio/Features/Downloads/VideoDownloadManager.swift:145-155
Audio Download Manager
AudioDownloadManager handles standard binary downloads (e.g., MP3, AAC) using standard URLSessionDownloadTask.
- Storage: Files are saved directly to the app's
Documentsdirectory with a standardized naming convention:putio_adm_[ID]_[Slug].[extension]. - MIME Mapping: It derives file extensions from the server's
Content-Typeheader (e.g.,audio/x-m4ato.m4a).
Sources: Putio/Features/Downloads/AudioDownloadManager.swift:24-34, Putio/Features/Downloads/AudioDownloadManager.swift:125-132, Putio/Features/Downloads/AudioDownloadManager.swift:136-155
Download Workflow
Diagram illustrating the branching logic based on media type and the eventual persistence of the downloaded asset. Sources: Putio/Features/Downloads/AudioDownloadManager.swift:67-78, Putio/Features/Downloads/VideoDownloadManager.swift:90-101
Persistence and Recovery
The system includes a robust recovery mechanism to prevent data loss during app updates or Realm database migrations.
In-Memory/Database Sync
The DownloadsViewController uses Realm's NotificationToken to observe changes in the download collection, ensuring the UI stays synchronized with background transfer progress.
Sources: Putio/Features/Downloads/DownloadsViewController.swift:97-128
Recovery Mechanism
If the Realm database is deleted or becomes incompatible (e.g., during a major schema version jump from 9 to 10), the app enters a "Recovery" state.
- Tracking: Local file references are mirrored in
UserDefaults. - Reconstruction:
PutioRealm.recoverDownloadsIfNeeded()scansUserDefaultsfor video bookmarks and theDocumentsdirectory for audio files to rebuild the Realm records. - Enrichment: Recovered records initially use placeholder names (e.g., "Recovering..."). The system then calls the put.io API to fetch actual file names and sizes.
Sources: Putio/Common/Helpers/Realm.swift:85-110, Putio/Common/Helpers/Realm.swift:148-185, Putio/Common/Helpers/Realm.swift:245-275
Playback and UI Integration
Offline access is managed through the DownloadedFilePresenter protocol, which provides logic for playing local assets.
- Local URL Resolution: Before playback, the system validates that the file still exists on disk. For videos, it resolves the
UserDefaultsbookmark. For audio, it resolves the relative path against the currentDocumentsdirectory. - Error Handling: If a file is missing (e.g., deleted by the OS to save space), the system prompts the user to "Re-download" and marks the record as
Failedwith a "File not reachable" message. - UI Actions: The
DownloadsViewControllerprovides swipe-to-delete actions which trigger the respective manager to cancel active tasks and delete physical files.
Sources: Putio/Features/Downloads/DownloadedFilePresenter.swift:11-25, Putio/Features/Downloads/DownloadedFilePresenter.swift:37-45, Putio/Features/Downloads/DownloadsViewController.swift:150-184
Summary of Management Methods
| Action | Component | Implementation Detail |
|---|---|---|
| Start | createDownload(from:) | Adds record to Realm and resumes task in URLSession. |
| Cancel | cancelDownload(id:) | Cancels the specific URLSessionTask and updates state to .stopped. |
| Delete | deleteDownload(id:) | Cancels task (if active), deletes file from disk, and removes Realm record. |
| Restart | restartDownload(id:) | Re-fetches file metadata from API and initiates a fresh transfer. |
Sources: Putio/Features/Downloads/AudioDownloadManager.swift:80-111, Putio/Features/Downloads/VideoDownloadManager.swift:103-134