Разработка системы подписок на пользователей в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Разработка системы подписок на пользователей в мобильном приложении
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Разработка системы подписок на пользователей в мобильном приложении

Подписки — основа социального графа приложения. Технически это таблица follows (follower_id, followee_id, created_at) с UNIQUE-ограничением. Но детали в UI, производительности запросов и уведомлениях определяют, насколько система будет работать при росте аудитории.

Схема данных и запросы

Таблица follows:

CREATE TABLE follows (
    follower_id  BIGINT NOT NULL,
    followee_id  BIGINT NOT NULL,
    created_at   TIMESTAMP DEFAULT NOW(),
    PRIMARY KEY (follower_id, followee_id)
);
CREATE INDEX idx_follows_followee ON follows (followee_id);

Индекс на followee_id нужен для быстрого подсчёта подписчиков: SELECT COUNT(*) FROM follows WHERE followee_id = ?. Без него при 1M записях — full scan.

Денормализация: users.followers_count и users.following_count — обновляется триггером или через очередь. Счётчик в профиле берётся из денормализованного поля, не из COUNT.

Взаимная подписка (mutual follow): SELECT 1 FROM follows WHERE follower_id = $1 AND followee_id = $2 — проверяем оба направления. Можно кэшировать в Redis: SISMEMBER user:{id}:following {target_id}.

Кнопка Follow/Unfollow

Оптимистичное обновление обязательно — кнопка переключается мгновенно:

// iOS
func toggleFollow(userId: String, currentlyFollowing: Bool) {
    let optimisticState = !currentlyFollowing
    updateFollowButton(isFollowing: optimisticState)

    let request = optimisticState ? apiService.follow(userId) : apiService.unfollow(userId)
    request.sink(
        receiveCompletion: { [weak self] completion in
            if case .failure = completion {
                self?.updateFollowButton(isFollowing: currentlyFollowing) // откат
            }
        },
        receiveValue: { _ in }
    ).store(in: &cancellables)
}

На Compose — followState: Boolean в ViewModel, изменяется до запроса, откатывается при ошибке.

Три состояния кнопки: «Подписаться», «Подписан», «Отписаться» (последнее показывается при лонг-тапе или hover). Не показывайте кнопку «Отписаться» как основной текст — пользователи принимают за подтверждение подписки.

Закрытые аккаунты (Private accounts)

Если приложение поддерживает закрытые профили: follow_request вместо немедленной подписки. Новая таблица follow_requests (requester_id, target_id, status, created_at). Целевой пользователь видит входящие заявки, принимает/отклоняет. При принятии — запись перемещается в follows. Push-уведомление при новой заявке и при принятии.

Список подписчиков/подписок

Пагинация cursor-based по created_at DESC или по follower_id (для стабильного порядка). Для каждого пользователя в списке показываем isFollowedByMe — требует JOIN или batch-проверки. Batch-вариант: SELECT followee_id FROM follows WHERE follower_id = ? AND followee_id IN (?) — один запрос для всей видимой страницы.

На iOS — UITableView с UITableViewDiffableDataSource, каждая ячейка содержит аватар, имя, кнопку Follow с состоянием. Prefetch: UITableViewDataSourcePrefetching запрашивает следующую страницу за 3 ячейки до конца.

На Android — LazyColumn с Paging 3, RemoteMediator для network + local cache.

Уведомления при подписке

При новой подписке — push-уведомление автору профиля: «Иван подписался на вас». FCM/APNs через бэкенд. Deeplink — на профиль подписавшегося. Батчинг: если за минуту подписалось 5 человек — одно уведомление «5 новых подписчиков», не пять отдельных.

Рекомендации «Кого подписаться»

Простая эвристика: пользователи, на которых подписаны мои подписки, но на которых не подписан я («friends of friends»). SQL:

SELECT DISTINCT f2.followee_id
FROM follows f1
JOIN follows f2 ON f1.followee_id = f2.follower_id
WHERE f1.follower_id = :me
  AND f2.followee_id != :me
  AND NOT EXISTS (SELECT 1 FROM follows WHERE follower_id = :me AND followee_id = f2.followee_id)
LIMIT 20;

Для больших графов — предрасчёт через воркер, результат в Redis.

Сроки

Базовая система (follow/unfollow, счётчики, список) — 1-2 дня. С закрытыми аккаунтами, уведомлениями, рекомендациями — 3-5 дней. Стоимость рассчитывается индивидуально.