Розроблення мобільного додатка для трекінгу настрою
Трекер настрою виглядає простим додатком рівно до того моменту, поки не почнеш розбиратися в деталях: як зберігати суб'єктивні оцінки, щоб потім з них вийшла осмислена аналітика, як будувати графіки динаміки без візуального шуму, як відправляти нагадування, які не дратують і не тонуть у Do Not Disturb. Це не «зроби CRUD на Firebase» — це продумана система роботи з емоційними даними.
Що реально ускладнює завдання
Головна технічна складність — модель даних. Настрій можна оцінювати за п'ятибальною шкалою, за шкалою валентності-arousal, з еморджи, з тегами контексту. Якщо структуру закласти неправильно, то через місяць користувач бачить невалідні графіки або взагалі не може порівняти минулий місяць з поточним.
Друга біль — нагадування. UNUserNotificationCenter на iOS дає тільки 64 pending-сповіщення. При індивідуальному розкладі на кожен день тижня цей ліміт згорає миттєво. Потрібно либо генерувати сповіщення динамічно через BGAppRefreshTask, либо використовувати повторюючі тригери з локальною логікою. На Android WorkManager з PeriodicWorkRequest надійніше, але й там Doze Mode реже доставку при агресивних налаштуваннях енергозбереження.
Третя історія — аналітика. Скользяче середнє за 7 днів, кореляція настрою з активністю з HealthKit (кроки, сон), кластеризація паттернів за днями тижня. Все це рахується на клієнті — і якщо не кешувати результати агрегації, то кожен відкритий екран аналітики перечитує весь CoreData store з помітною затримкою.
Як будуємо
Архітектурно — MVVM з Combine (iOS) або ViewModel + StateFlow (Android). Локальне сховище: CoreData з NSPersistentCloudKitContainer для iCloud-синку або Room + DataStore для Android. Бекенд потрібен не завжди — багато проектів працюють повністю offline-first.
Для кросс-платформеної версії на Flutter використовуємо Isar як вбудовану БД замість SQLite: він швидший при складних індексованих запитах і добре лягає на реактивну модель через watchLazy. Riverpod управляє станом, charts_flutter або fl_chart — візуалізація.
Конкретний кейс: додаток з трекером настрою + дневником. Користувач вносить запис — ми зберігаємо MoodEntry з timestamp, числовою оцінкою, enum-тегами (work, sleep, exercise, social) та опціональним текстом. Раз на добу фонова задача пересчитує агрегати за останні 30 днів і кладе їх у окрему таблицю MoodAggregate. Екран аналітики читає тільки агрегати — ніяких важких запитів до основного сховища.
Інтеграція з HealthKit (iOS) — запитуємо HKQuantityTypeIdentifier.stepCount та sleepAnalysis за період, коррелюємо з mood-даними через просту лінійну регресію на клієнті. Користувачі бачать: «у дні, коли ви робили 8000+ кроків, ваш настрій у середньому на 0.8 балу вище».
Процес роботи
Спочатку — аудит вимог: які метрики трекати, потрібен ли бекенд (мульти-пристрої, шеринг з психологом), цільові платформи, потрібна ли інтеграція з HealthKit/Google Fit. Потім — проектування моделі даних та екранів, прототипування в Figma, розроблення, тестування (XCTest / Espresso для unit, ручне на фізичних пристроях), публікація.
Орієнтири за термінами
MVP з журналом, базовою аналітикою та нагадуваннями — 3–5 тижнів. Повноцінний додаток з HealthKit/Google Fit, iCloud-синком, експортом PDF та onboarding — 8–12 тижнів. Вартість розраховується індивідуально після аналізу вимог.
Типові помилки при самостійній розробці
- Зберігати mood-записи як рядки замість нормалізованих enum'ів — потім аналітика неможлива без міграції.
- Запускати агрегацію на main thread в
viewDidAppear— користувач бачить фриз при відкритті аналітики. - Ігнорувати часові пояси: якщо користувач перелетів у іншу країну, записи за «сьогодні» потрапляють у «вчора». Зберігати UTC, відображати в локальному часовому поясі.
- Просити дозвіл на сповіщення при першому запуску без пояснення — відмова від дозволу обнулює всю логіку нагадувань назавжди (повторно запросити не можна, тільки через Settings).







