This document explains the mobile caching implementation in the Spawn App iOS codebase.
The Spawn App iOS client implements a sophisticated caching mechanism to reduce API calls, speed up the app's responsiveness, and provide a better user experience. This is achieved through:
- Client-side caching: Storing frequently accessed data locally
- Cache invalidation: Checking with the backend to determine if cached data is stale
- Push notifications: Receiving real-time updates when relevant data changes
The AppCache
class is a singleton that manages the client-side cache:
- Stores cached data in memory using
@Published
properties for reactive SwiftUI updates - Persists cached data to disk using
UserDefaults
- Validates cache with backend on app launch
- Provides methods to refresh different data collections
Example of using the AppCache:
// Access cached friends in a view
struct FriendsListView: View {
@EnvironmentObject var appCache: AppCache
var body: some View {
List(appCache.friends) { friend in
FriendRow(friend: friend)
}
}
}
The app makes a request to /api/v1/cache/validate/:userId
on startup, sending a list of cached items and their timestamps:
{
"friends": "2025-04-01T10:00:00Z",
"events": "2025-04-01T10:10:00Z",
"notifications": "2025-04-01T10:05:00Z"
}
The backend responds with which items need to be refreshed:
{
"friends": {
"invalidate": true,
"updatedItems": [...] // Optional
},
"notifications": {
"invalidate": false
},
"events": {
"invalidate": true
}
}
The app listens for push notifications with specific types that indicate data changes:
friend-accepted
: When a friend request is acceptedevent-updated
: When an event is updatednew-notification
: When a new notification is created
When these notifications are received, the app refreshes the relevant cached data.
- On app launch,
AppCache
loads cached data from disk - The app sends a request to validate the cache with the backend
- For invalidated cache items:
- If the backend provides updated data, it's used directly
- Otherwise, the app fetches the data with a separate API call
- As the user uses the app, they see data from the cache immediately
- In the background, the app may update cache items based on push notifications
- App loads cached data → UI renders immediately
- App checks if cache is valid → Updates UI if needed
- User interacts with fresh data → Great experience!
- Speed: UI renders instantly from cache
- Bandwidth: Reduced API calls
- Battery: Less network activity
- Offline Use: Basic functionality without network
To verify the cache is working:
- Launch the app and navigate to a screen that displays cached data (e.g., friends list)
- Put the device in airplane mode
- Close and reopen the app
- The data should still be displayed, loaded from the cache
The current implementation has some limitations:
- Cache is stored in
UserDefaults
, which has size limitations - No encryption for cached data
- No automatic pruning of old cached data
- Limited offline editing capabilities
These could be addressed in future updates.
The backend needs to implement the cache validation endpoint as described in cache-validation-api-spec.md
.
Additionally, the backend should send appropriate push notifications when data changes that would affect a user's cache.