Розробка системи хештегів у мобільному додатку
Користувач вводить пост, ставить # і чекає підказки. Dropdown зависає, не на тих позиціях, або клавіатура його перекриває — класичні проблеми системи хештегів. Ми вирішуємо їх стеком перевірених рішень: дебаунс запитів 200 мс, позиціонування через caretRect на iOS і Popup з offset на Android, кастомні regex для Unicode. Наша команда інтегрувала такі системи в 20+ проєктах — від соціальних мереж до трекерів звичок. У результаті додатки показують на 25% більше переглядів на користувача.
В основі системи лежать три ключові компоненти: клікабельне виділення хештегів у тексті, автодоповнення при введенні та сторінка тега зі стрічкою контенту. Кожен потребує детального опрацювання, особливо на високих навантаженнях. Нижче розберемо реалізацію кожного блоку.
Парсинг і виділення в тексті
Хештег у тексті має бути клікабельним і візуально виділятися — синім або фірмовим кольором. На iOS це NSAttributedString з кастомними атрибутами:
func attributedText(from text: String) -> NSAttributedString { let attributed = NSMutableAttributedString(string: text) let hashtagPattern = #"#[\w\u0400-\u04FF]+"# // поддержка кириллицы let regex = try! NSRegularExpression(pattern: hashtagPattern) let matches = regex.matches(in: text, range: NSRange(text.startIndex..., in: text)) for match in matches { attributed.addAttribute(.foregroundColor, value: UIColor.systemBlue, range: match.range) attributed.addAttribute(.link, value: "hashtag://\(match.range)", range: match.range) } return attributed } Обробка тапа — через UITextView.delegate метод textView(_:shouldInteractWith:in:interaction:). Перехоплюємо URL-схему hashtag:// і відкриваємо екран тега.
На Compose — AnnotatedString з SpanStyle:
buildAnnotatedString { val hashtagRegex = Regex("#[\\w\\u0400-\\u04FF]+") var lastIndex = 0 hashtagRegex.findAll(text).forEach { match -> append(text.substring(lastIndex, match.range.first)) pushStringAnnotation("HASHTAG", match.value) withStyle(SpanStyle(color = MaterialTheme.colorScheme.primary)) { append(match.value) } pop() lastIndex = match.range.last + 1 } append(text.substring(lastIndex)) } Важно: regex для хештегів має підтримувати не тільки ASCII, але й кирилицю, арабську та інші Unicode-алфавіти — \w у більшості реалізацій не покриває їх без явного зазначення Unicode-діапазонів. Ми використовуємо патерн #[\p{L}\p{N}_]+ у мовах з підтримкою Unicode властивостей.
Автодоповнення при введенні
При введенні # у поле створення посту запускаємо пошук по базі хештегів. Логіка:
- Відстежуємо позицію курсора в тексті.
- Шукаємо
#перед курсором без пробілів. - Текст після
#— пошуковий запит. - Запитуємо
GET /hashtags/suggest?q=спз дебаунсом 200 мс. - Показуємо dropdown під полем введення (не над ним — клавіатура перекриває).
На iOS dropdown — окремий UITableView, що додається в UIWindow поверх основного контенту. Позиціонуємо по caretRect(for:) з UITextInput. При виборі хештега зі списку — вставляємо в текст через replace(_:withText:) і прибираємо dropdown.
| Платформа | Компонент | Позиціонування |
|---|---|---|
| iOS | UITableView в UIWindow | caretRect(for:) |
| Android | ExposedDropdownMenuBox або Popup | offset від поля введення |
Наш підхід з дебаунсом знижує навантаження на сервер у 3 рази порівняно із запитами на кожне натискання. А використання індексу на LOWER(name) прискорює пошук у 10 разів порівняно з повнотекстовим пошуком без індексу — це особливо помітно при базі зі 100 000 хештегів.
Деталі реалізації трендових хештегів
Для трендових хештегів використовується воркер, який рахує кількість постів за останні 24 години та кешує результат у Redis на 30 хвилин. Дані оновлюються кожні 10 хвилин, щоб уникнути пікового навантаження на базу.База хештегів та аналітика
Таблиця hashtags (id, name, posts_count). При публікації посту парсимо хештеги, шукаємо або створюємо запис у hashtags, створюємо зв'язок post_hashtags (post_id, hashtag_id). posts_count оновлюється через чергу.
Сторінка хештега — GET /hashtags/{name}/posts з пагінацією. Сортування за датою або за популярністю (posts з найбільшим engagement за останні N днів). Trending hashtags: воркер рахує posts_count за останні 24 години, результат кешується в Redis на 30 хвилин.
Чому хештеги важливі для залученості?
Хештеги дозволяють користувачам легко знаходити контент за темами, підвищуючи час сесії та повернення. За нашими даними, додатки з системою хештегів показують на 25% більше переглядів на користувача. Правильна реалізація гарантує плавну роботу без лагів. Зв'яжіться з нами, щоб обговорити вашу задачу.
Як ми гарантуємо якість реалізації?
Ми використовуємо модульні тести для парсингу та автодоповнення, інтеграційне тестування з реальним API та навантажувальне тестування для оцінки продуктивності. Кожен проєкт проходить code review та перевірку на відповідність стандартам App Store і Google Play.
Нормалізація імен
Хештеги нечутливі до регістру: #React, #react, #REACT — один тег. Зберігаємо в lowercase, при пошуку — LOWER(name) = LOWER(?) або індекс на LOWER(name). Пробіли та спецсимволи в імені хештега — прибираємо при нормалізації.
Що входить у роботу?
- Парсинг і клікабельні хештеги в тексті
- Автодоповнення при введенні з дебаунсом
- Сторінка тега з пагінацією
- База даних і API для хештегів
- Трендові хештеги та аналітика
- Документація та навчання команди
- Гарантія підтримки протягом 1 місяця після здачі
Строки
Парсинг і клікабельні хештеги в тексті — 1 день. Автодоповнення при введенні — ще 1 день. Сторінка тега зі стрічкою — 1-2 дні. Повна система — 2-3 робочих дні. Вартість розраховується індивідуально. Отримайте консультацію, щоб ми оцінили ваш проєкт.







