Как я написала 4-мегабайтный блокировщик соцсетей под iOS
История о том, как борьба с дофаминовыми ловушками вылилась в разработку собственного нативного блокировщика соцсетей под iOS Scroll Brake, почему популярные аналоги требуют странные разрешения и как обойти неочевидные грабли в Apple Screen Time API.
Зачем мне вообще понадобился блокировщик соцсетей под iOS
Я очень трепетно отношусь к продуктивности. За годы работы я собрала собственную систему управления временем и энергией, которая отлично держит структуру дня и помогает закрывать задачи.
Но бывают моменты, когда просто на автомате берешь телефон в руки и начинаешь залипать в рилсы. Одно короткое видео, второе, третье: лента постоянно подсовывает что-то интересное. Вроде только зашла на пару минут, а очнулась, когда прошло уже 40 минут или целый час. Алгоритмы соцсетей созданы лучшими инженерами мира с одной целью: удерживать внимание любой ценой. Каждое следующее видео интереснее предыдущего, и мозг проваливается в бесконечную дофаминовую петлю.
Я не собиралась писать свое приложение. Как разработчица и фаундер я ценю время и предпочитаю использовать готовые решения. Поэтому я пошла в App Store искать существующие инструменты.
Что не так с современным рынком блокировщиков?
Я протестировала популярные приложения ниши: Opal, OneSec, ScreenZen, Refocus и стандартный Screen Time от Apple. И почти сразу наткнулась на вещи, которые вызвали у меня откровенное недоумение:
Парадокс уведомлений и приватности
Первое, что делают почти все такие приложения: сразу просят доступ к уведомлениям и аналитике. Зачем сервису, который призван убрать телефон из рук, слать мне пуши? Как выяснилось уже во время разработки, дело в давнем системном ограничении Apple (дальше в технической части разберу подробнее).
Агрессивные экраны оплаты
Не успеваешь открыть главный экран и понять, решает ли сервис твою проблему, а тебе уже навязчиво выкатывают подписку с «бесплатным триалом», расчет в котором явно строится на том, что пользователь просто забудет отписаться. Как предпринимательница я понимаю эту воронку, но как пользователя меня передергивает от такого подхода.
Бесполезность стандартного Apple Screen Time
Встроенный лимит от Apple не работает психологически. Когда всплывает стандартный системный экран блокировки, рука на автомате жмет «Игнорировать лимит на 15 минут». Здесь нет когнитивного барьера, действие совершается машинально.
Тратить время на перебор десятков клонов с одинаковыми экранами подписки не хотелось. Я поняла: быстрее и честнее сделать ультра-легкий нативный инструмент под себя.
Принципы Scroll Brake: 4 МБ, без трекеров и подписок
В NovaSynapse мы придерживаемся принципа «Всё, что нужно. Ничего лишнего» (Everything you need. Nothing you don’t). Приложение должно решать задачу, не жрать батарею и уважать границы пользователя.
Так родился Scroll Brake:
- Вес всего ~4 МБ: Никаких тяжелых фреймворков, веб-вью и раздутых зависимостей.
- 100% Privacy-First: Никакой регистрации, никаких баз данных, никаких внешних серверов. Всё исполняется локально на устройстве через нативные API iOS.
- Когнитивное трение вместо тупого запрета: Чтобы продлить время в соцсетях, нужно включить префронтальную кору и решить математический пример. Это сбивает автопилот.
- Антидофаминовый UX вместо геймификации: После правильного решения примера я намеренно не показываю экран с фейерверками, конфетти и не поздравляю с решением. Подкармливать мозг дешевым дофамином за шаг к соцсетям просто абсурдно. Экран намеренно сделан максимально скучным: таймер разблокирован, а для быстрого возврата используется стандартная кнопка перехода в предыдущее приложение в левом верхнем углу (в iOS из соображений приватности хост-приложение не может знать, из какого именно сервиса сработал лимит, поэтому возврат происходит через системный breadcrumb).
- Монетизация: До 3 правил приложение бесплатное (мне для себя хватает ровно одного правила: категория «Соцсети» не более 5 минут в день). Для тех, кому нужно больше, сделала разовую покупку навсегда (Lifetime) вместо обязательных подписок.
Как велась разработка: 4 дня, AI и инструменты Xcode
Приложение я писала с помощью AI: использовала Antigravity с моделями Gemini (3.1 Pro и Flash).
Раньше я уже пробовала писать мобильные приложения на Flutter и нативно, но до эпохи AI-ассистентов на это уходило куда больше времени. Здесь же всё получилось собрать довольно быстро. Слепо принимать сгенерированный код, конечно, нельзя: системные расширения у Apple капризные, поэтому код-ревью я делала сама, чтобы ничего не крашилось и не текло по памяти. Но в целом разработка шла легко и заняла буквально 3–4 чистых рабочих дня со всеми тестами на эмуляторе и реальном телефоне:
- Иконка за 15 минут: Вместо ручной отрисовки десятка PNG-ассетов я использовала Icon Composer из Developer Tools в Xcode. С его помощью векторные слои автоматически адаптируются под светлую, темную и тонированную темы iOS.
- App Store Review < 24 часов: Поскольку в приложении нет скрытого трекинга, сторонних SDK и сбора персональных данных, модерация Apple без лишних вопросов одобрила релиз в App Store уже на следующий же день после отправки.
Инженерный разбор: скрытые грабли Screen Time API
А теперь самое интересное: техническая изнанка работы со связкой ManagedSettings, DeviceActivity и FamilyControls. Если вы решите разрабатывать утилиту под Screen Time, вы неизбежно упретесь в три системных барьера. Вот как я их решила:
Почему конкуренты просят Push-уведомления? (iOS < 26.5 vs iOS 26.5+)
Многие пользователи ругают приложения за спам уведомлениями, но мало кто знает, что разработчики долгое время были заложниками архитектуры Apple.
- Проблема старых версий:
Когда приложение блокируется, система показывает системный экран защиты: ShieldActionExtension. В нем пользователь нажимает кнопку «Продлить». Но расширение исполняется в урезанном процессе, где вызов UIApplication.shared.open запрещен на уровне компилятора и системы. Enum ShieldActionResponse поддерживал только сценарии .close, .defer и .none. Открыть хост-приложение для ввода кода или решения примера напрямую было невозможно!
- Костыль индустрии:
Единственным способом перебросить пользователя в приложение была отправка локального push-уведомления (UNUserNotificationCenter). Пользователю требовалось вручную свайпнуть шторку или тапнуть баннер уведомления, чтобы открыть приложение. Именно поэтому почти все аналоги просят разрешение на нотификации.
- Мое решение в iOS 26.5+:
Apple наконец добавила нативный кейс ответа ShieldActionResponse.openParentalControlsApp. При его возврате система сама мгновенно переносит пользователя в главное приложение к экрану решения математического примера (MathPuzzleView):
// ShieldActionExtension.swift
defaults?.set(true, forKey: "launchedFromShieldAction")
completionHandler(.openParentalControlsApp)
Я зафиксировала минимальную версию проекта на современном таргете (IPHONEOS_DEPLOYMENT_TARGET = 26.5), полностью исключив костыли с push-уведомлениями из архитектуры.
Запрет на прямое чтение статистики использования (песочница приватности)
Меня часто спрашивают: «Почему приложение не показывает детальный поминутный график активности внутри каждого приложения в кастомной аналитике?»
Ответ прост: Apple архитектурно изолирует данные об использовании от хост-приложения.
- Доступ к массиву
DeviceActivityResultsпредоставляется исключительно расширению DeviceActivityReportExtension, которое исполняется в изолированном системном процессе. - Хост-приложение встраивает лишь визуальный контейнер DeviceActivityReport. Он рендерится удаленно (out-of-process remote rendering) и проецируется в интерфейс приложения.
- Данные не покидают песочницу расширения: приложение не может сохранить их в локальную БД, преобразовать в массивы или отправить по сети.
Официальная позиция Apple прямо фиксирует это ограничение:
«Для защиты приватности пользователя расширение DeviceActivityReport работает в изолированной песочнице, и его данные не покидают пределов расширения. Вместо этого расширение создает и возвращает графические представления (views), которые отображает ваше приложение».
- Следствие для мониторинга:
Отслеживание лимитов через DeviceActivityCenter строится исключительно на подписке на пороговые значения (DeviceActivityEvent.threshold). Система уведомляет расширение DeviceActivityMonitorExtension только в момент, когда порог достигнут (eventDidReachThreshold), не отдавая промежуточных значений использования.
- Почему возврат происходит по кнопке в левом верхнем углу:
В iOS хост-приложение принципиально не может знать, из какого именно приложения сработал щит блокировки: система не передает bundleIdentifier ради защиты приватности. Из-за этого приложение не может программно переключить пользователя обратно в условный Instagram или TikTok. Возврат осуществляется через стандартную системную стрелку перехода в предыдущее приложение в левом верхнем углу статус-бара iOS.
Баги Screen Time API, которые пришлось устранять вручную
В ходе тестов я столкнулась с системными багами самой iOS, которые способны сломать любой блокировщик:
Баг кэширования порогов в DeviceActivityCenter (Event Caching Bug)
- Баг: При обновлении порога для существующего
DeviceActivityName(при продлении времени) iOS не сбрасывала внутренний триггер и игнорировала новыйthreshold. - Решение: Генерация уникального имени активности с токеном сессии
DeviceActivityName("limit_с предварительным вызовом_ ") stopMonitoring(). - Документация Apple: DeviceActivityCenter.startMonitoring.
deviceActivityCenter.stopMonitoring([previousActivityName])
let newActivity = DeviceActivityName("limit_\(UUID().uuidString)_\(sessionToken)")
try deviceActivityCenter.startMonitoring(newActivity, during: schedule, events: events)
Баг сброса на следующий день (Dual-Event Schedule Pattern)
- Баг: Расписание DeviceActivitySchedule с параметром
repeats: trueи уменьшенным порогом продления (например, 1 мин) на следующий день запускало тот же 1-минутный порог вместо суточной нормы. - Решение: Регистрация двух событий в одном расписании:
mainEvent(полный суточный лимит на завтра) иextEvent(с зашитой датой в имени события, активное только в текущие сутки до 23:59).
Краши OOM (Out-Of-Memory, код 11) в DeviceActivityReport
- Баг: Наличие реактивных таймеров в SwiftUI-иерархии вызывало непрерывную переоценку
DeviceActivityReport. Это провоцировало многократную агрегацию 7-дневных логов по XPC и приводило к утечке памяти и моментальному завершению процесса системой по OOM. - Решение: Полный отказ от реактивных таймеров в UI, фиксация фильтра отчета без постоянных мутаций и обновление данных строго по событиям жизненного цикла (
onAppear,willEnterForeground).
Как я настроила приложение для себя
С момента релиза Scroll Brake стал моим главным барьером от залипания в телефоне.
У меня это настроено так:
- Одно правило: категория «Соцсети» (Social Networks) заблокирована.
- Базовый лимит: 5 минут в день.
- Продление: 5 минут за решение математического примера.
- Жесткий лимит: не более 5 продлений в сутки.
В итоге я физически не могу провести в соцсетях больше 25 минут в день. При этом мозг привык: чтобы зайти посмотреть присланный рилс, нужно решить задачу. Этого секундного трения оказывается достаточно, чтобы 8 раз из 10 просто положить телефон экраном вниз и вернуться к делам.
UPD (Октябрь 2026): Strict Mode, умная калибровка и выход в Chrome
С момента публикации статьи прошло время, и Scroll Brake получил несколько важных обновлений, а само приложение в App Store я переименовала в предельно понятное: Scroll Brake: Math App Blocker.
Концепция доказала свою жизнеспособность: математический барьер оказался самым тихим, естественным и универсальным способом остановить автопилот. Вам не нужно приседать перед камерой, искать штрихкод на упаковке кофе или слушать сирены: решить уравнение в уме занимает 5–15 секунд и работает в любой обстановке (в переполненном метро, на скучном совещании или дома перед сном).
Вот главные выводы и новые возможности, которые появились по итогам реальной эксплуатации:
Модерация Apple: от суток до 3 часов
Пожалуй, самый приятный сюрприз: если первый релиз проверялся почти сутки, то последующие обновления версий модераторы Apple одобряют молниеносно: последнее обновление пропустили всего за 3 часа. Чистый код без сторонних SDK, трекеров и сомнительных разрешений творит чудеса.
Строгий режим (Strict Mode): когда мозг наловчился считать
Практика показала занятный феномен: в моменты сильного стресса мозг способен адаптироваться и на автомате решить 3–4 примера подряд, лишь бы добраться до заветной ленты. Чтобы закрыть эту лазейку, я добавила Strict Mode:
- Лимит разблокировок на день (Daily Unlock Cap): Можно задать жесткую квоту продлений (например, не больше 4–5 раз в сутки).
- Сессии вместо сплошного часа: Гораздо эффективнее нарезать доступ интервалами по 10 минут. Каждые 10 минут экран снова блокируется, возвращая контроль сознанию.
- Замок до полуночи: Как только дневной лимит продлений исчерпан, замок защелкивается намертво: ни одно правильное решение не снимет блокировку до 00:00.
- Без поблажек на выходные: В приложении я сознательно не стала делать разделения на будни и выходные. Дофаминовые привычки не сверяются с календарем: безлимитный скролл в субботу мгновенно обнуляет дисциплину всей рабочей недели.
Автокалибровка сложности при первом запуске
Чтобы математический барьер не вызывал отторжения у тех, кто не любит устный счет, я добавила быструю калибровку на этапе знакомства с приложением: 3 разминочных вопроса за 1 минуту определяют комфортный уровень (от базового сложения до устного умножения двузначных чисел). Более того, алгоритм адаптивен: устали к вечеру и ошиблись: сложность мягко снижается; щелкаете задачи за секунды: плавно растет, удерживая концентрацию в тонусе.
Выход на десктоп: расширение для Chrome
Когда смартфон перестал быть дофаминовой ловушкой, рефлекс попытался мигрировать на рабочий ноутбук: рука за кодом на автомате открывала вкладки с Reddit, Twitter или YouTube.
Чтобы закрыть эту брешь, в NovaSynapse мы выпустили официальное расширение Scroll Brake для Chrome (работает во всех Chromium-браузерах: Brave, Microsoft Edge, Opera, Vivaldi):
- Manifest V3 и чистый JS: Легковесно, без тяжелых фреймворков и с нулевым влиянием на батарею.
- 100% Privacy & Zero Sync: Никаких аккаунтов и облачных баз. Все настройки живут в локальном
chrome.storage, что позволяет держать полностью независимые правила для рабочего и личного профилей браузера. - True Active-Time Tracking: Время сессии списывается только при реальной активности (движение курсора, скролл, ввод текста). Переключили вкладку или свернули браузер: таймер сразу на паузе.
- Хирургическая блокировка: Можно заблокировать сайт целиком, а можно точечно отрезать только пожиратели времени вроде
youtube.com/shorts*, сохранив доступ к полезным лекциям и технической документации.
Мои текущие настройки
Сейчас связка держит мой фокус на двух устройствах:
- На iPhone: Соцсети заблокированы (5 мин базово + продление по 5 мин, максимум 4 раза в Strict Mode: не более 25 минут в день).
- В Chrome: Блокировка лент Reddit, X и YouTube Shorts с аналогичным ментальным барьером и учетом только активного времени.
Этого секундного трения устного счета по-прежнему хватает в 9 случаях из 10, чтобы просто закрыть вкладку или отложить телефон и вернуться к реальным делам.