Reactive Data Persistence with Custom Combine Publishers
AdventureTube uses Core Data for local persistence of adventure stories, chapters, and geographic locations.
Entity Relationship Diagram
StoryEntity (1) ─── chapters (ordered) ──> (N) ChapterEntity
└─── places ───────────────> (N) PlaceEntity
↑ (1:1)
ChapterEntity (1) ─── place ──────────────────┘
Core Entities
StoryEntity
- YouTube video metadata (id, title, description, thumbnails)
- User metadata (contentType, tripDuration, isPublished)
- Relationships: chapters (NSOrderedSet), places (NSSet)
ChapterEntity
- Timestamped segments (youtubeTime, category, thumbnail)
- Relationships: place (1:1), story (many-to-one)
PlaceEntity
- Geographic data (latitude, longitude, placeID, name)
- Google Places metadata (rating, types, photos)
- Relationships: chapter (1:1), story (many-to-one)
CoreDataManager
Singleton pattern for data management:
- Auto-merge changes from background contexts
- Simple save/fetch API
- Reactive observation with Combine
Custom Combine Publishers
1. CoreDataFetchResultsPublisher
One-time reactive fetch operations
2. CoreDataSaveModelPublisher
Reactive save operations with error handling
3. CoreDataStorage
Cross-context reactive observation with change tracking:
.inserted– New entities.updated– Modified entities.deleted– Removed entities
Best Practices
✅ Use viewContext for UI operations
✅ Use background contexts for heavy operations
✅ Observe changes with didSavePublisher
✅ Maintain chapter order with NSOrderedSet
✅ Use fetch requests with sort descriptors
❌ Don’t save on main thread for large operations
❌ Don’t ignore merge conflicts
❌ Don’t forget to set inverse relationships


