TGViewer
Channel Public Channel
Мобильная разработка

Мобильная разработка

@mobi_dev

Актуальное по мобильной разработке — Android, iOS, кроссплатформа

Разместить рекламу: @tproger_sales_bot
Правила общения: https://tprg.ru/rules
Другие каналы: @tproger_channels
Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/oVBP
Subscribers
13.2K
Photos
949
Videos
237
Links
3.1K
Recent Posts 20 shown
Post #4752 448
Как ProfilingManager на Android 15+ помогает искать причины тормозов в продакшене

ProfilingManager собирает на устройствах трассировки процессора, образцы стека вызовов и дампы памяти. Datadog встроила API в мониторинг реальных пользователей: теперь команда видит не только долгий запуск или зависание главного потока, но и код с событиями системы, которые привели к проблеме.

Показательный случай: трассировка раскрыла, что фоновый сервис синтеза речи заранее запускался вместе с приложением, занимал самое производительное ядро процессора и заставлял главный поток ждать.

В разборе Android Developers' Blog описаны сбор миллионов профилей в неделю, встроенное ограничение частоты запросов и анализ трассировок через Perfetto. API доступен с Android 15, поэтому на более старых устройствах текущие средства телеметрии всё ещё нужны.
  • 🎉 1
Post #4751 587
Как использовать свайп-действия вне List в SwiftUI

В SwiftUI свайп-действия вроде удаления больше не привязывают интерфейс к List. Для ScrollView с LazyVStack или собственного Layout достаточно оставить swipeActions у строки и добавить контейнеру модификатор swipeActionsContainer().

Он не только включает жесты: следит, чтобы действия были раскрыты лишь у одной строки, и закрывает их при прокрутке или касании снаружи. В List эта логика уже встроена, поэтому отдельный модификатор там не нужен.

Приём пригодится, когда экрану нужна нестандартная компоновка или собственный стиль, но хочется сохранить нативное свайп-взаимодействие. Код для ScrollView и пользовательского Layout автор показывает в статье «Swipe actions outside of List in SwiftUI».
  • 👍 1
Post #4750 676
Как переносить сложные Android-экраны на Jetpack Compose: опыт TikTok

Команда TikTok переносила отдельные пользовательские сценарии и после каждого этапа сверяла метрики: начала с QR-кода, затем взялась за вход и регистрацию.

При небольших изменениях время загрузки страниц сократилось на 20–30%, а для новых функций и полностью переписанных страниц — на 70–80%. Та же функция на Compose потребовала на 58% меньше кода, чем реализация на View.

Практический нюанс: множество маленьких ComposeView внутри одного ViewHolder добавляло расходы на композицию. Один ComposeView на весь ViewHolder сработал лучше. Для пилота берите один сценарий и измеряйте результат до расширения миграции. В разборе Android Developers Blog есть также пример с ViewPager.
  • 🔥 6
Post #4749 798
Как управлять кнопками панели инструментов в SwiftUI

Одна и та же панель в SwiftUI ведёт себя по-разному: macOS показывает все действия справа сверху, а iOS часть оставляет вверху, остальные сворачивает в дополнительное меню. Новые API задают, что останется на виду.

visibilityPriority задаёт высокий или низкий приоритет, и SwiftUI сворачивает элементы с низким. ToolbarOverflowMenu помещает группу в свёрнутое меню на всех платформах. topBarPinnedTrailing удерживает действие справа сверху и может свернуть его только при активном поиске, если места не хватает.

toolbarMinimizeBehavior сворачивает панель вкладок, нижнюю, оконную или навигационную панель при прокрутке. Статья с примерами кода показывает все четыре API. Для iOS-команды схема такая: назначить приоритет ключевому действию, второстепенные убрать в меню, затем проверить интерфейс с активным поиском и при прокрутке.
  • ❤ 2
  • 👏 1
Post #4748 802
Как безопасно освобождать временные ресурсы с defer в Swift

В Swift блок defer выполняется перед выходом из ближайшей области видимости, которую задаёт пара фигурных скобок. Его можно поставить сразу после создания ресурса: код очистки останется рядом с настройкой, но сработает в конце функции, цикла или вычисляемого свойства.

Для iOS-разработки автор разбирает два сценария. В первом приложение записывает данные во временный файл, а defer удаляет его даже при раннем выходе после неудачного создания XMLParser. Во втором API наблюдения HealthKit требует вызвать обработчик завершения после обработки данных; defer делает это при выходе из итерации.

В статье с примерами кода также показано, как применять приём для снятия блокировок и восстановления изменённого состояния.
  • 👍 1
  • 👏 1
Post #4747 851
Как Flutter готовит приложения к новым версиям iOS

Между WWDC и стабильным релизом iOS у команды Flutter около трёх месяцев. В 2026 году скрипт на Dart выгрузил стенограммы более 145 сессий, а Gemini оценил их важность и область влияния. К вечеру команда получила разбор всех докладов.

Отдельный кейс в статье посвящён UIScene. Apple предупреждала: после iOS 26 UIKit-приложение, собранное последним SDK без UIScene, не запустится. Полная поддержка UIScene вошла во Flutter 3.41 в феврале 2026 года, до появления бета-версии iOS 27 с обязательной проверкой. Большинству разработчиков достаточно выполнить flutter upgrade; проекты со встраиванием Flutter в нативное приложение требуют ручной миграции, а плагины должны поддерживать UIScene.

В разборе команды Flutter есть и другой полезный кейс: сбой жестов в webview воспроизвели на чистом Swift, после чего Apple исправила его в iOS 26.4.
  • 🤝 1
Post #4746 943
Как проверять iOS-приложение из Cursor, Claude Code и Codex

RocketSim 17 выводит поток с iOS Simulator на локальную веб-страницу, которую можно открыть в браузере среды разработки. По команде /rocketsim агент проходит по экранам приложения и проверяет изменения через командную строку.

После прогона симулятор остаётся открыт. Разработчик выбирает элементы интерфейса прицелом, оставляет комментарии и возвращает их агенту в том же рабочем контексте. Слева видна иерархия доступности, снизу указаны рабочее дерево Git и ветка.

Такой цикл сокращает переключения между средой разработки и симулятором, но сохраняет визуальную проверку за человеком. В материале SwiftLee показан весь сценарий и объяснено, как подключить навигацию и проверку к агенту.
  • 👍 2
  • ❤ 1
Post #4745 973
Как установить рантаймы симуляторов Xcode из терминала

После установки Xcode 27 beta загрузка рантайма iOS у автора зависла на получении сведений. Переустановка Xcode и перезагрузка Mac не помогли, поэтому он перешёл к xcodebuild.

Сначала проверьте активную версию Xcode командой xcode-select -p. Если выбрана не та, переключите её: sudo xcode-select -s /Applications/Xcode-beta.app. Затем запустите xcodebuild -downloadPlatform iOS.

Если команда ищет универсальный рантайм и отвечает No matching downloadable, явно запросите arm64: xcodebuild -downloadPlatform iOS -architectureVariant arm64. Команду для загрузки рантаймов всех платформ и полный вывод ошибки смотрите в статье Донни Уолса.
  • 👍 2
  • ❤ 1
Post #4744 1.03K
Как безопасно перевести Flutter-код на первичные конструкторы Dart 3.12

В Dart 3.12 появилась экспериментальная поддержка primary constructors, или первичных конструкторов: поля класса и параметры конструктора можно объявить одной записью. В Flutter это сокращает шаблонный код виджетов, но массовая замена требует проверки поведения, а не только синтаксиса.

Попытка поручить миграцию агентам давала разные результаты даже при повторных запусках. Поэтому автор сделал детерминированную утилиту: она читает дерево кода через пакет Dart analyzer и применяет фиксированные правила.

Утилита выполняет три вида преобразований и пропускает код в 31 ситуации, когда безопасность замены нельзя доказать. Она записывает файл только после успешного разбора, а тесты проверяют результат анализатором. В инженерном разборе миграции показано, что именно нужно проверять кроме синтаксиса.
  • 💯 1
Post #4743 1.05K
Как настроить и обрабатывать диплинки в SwiftUI

Диплинк открывает нужный экран iOS-приложения сразу после перехода по ссылке. В примере схема recipeapp:// принимает действие open-recipe и параметр name, а SwiftUI получает адрес через onOpenURL.

Обработчик сверяет схему, разбирает адрес через URLComponents, проверяет действие и лишь затем читает имя рецепта. Если одну схему зарегистрируют несколько приложений, какое из них получит ссылку, не определено. Для однозначной привязки автор советует Universal Links.

Диплинки пригодятся и для экранов отладки или переключения тестовой среды. Открыть поддерживаемый адрес может кто угодно, поэтому принимайте только известные действия и параметры. В материале SwiftLee показаны настройка URL Types в Xcode, варианты для AppDelegate и SceneDelegate и тестирование ссылок в RocketSim.
  • 💯 1
Post #4742 1.01K
Как собрать переиспользуемую пагинацию во Flutter на Riverpod

Материал разбирает бесконечную ленту на Flutter без отдельного пакета пагинации. Автор строит общий контроллер поверх AsyncNotifier: один тип задаёт элементы списка, второй задаёт индекс страницы. Поэтому индексом может быть не только число, но и дата или строка.

Подключаемая примесь хранит текущий индекс, загружает первую страницу и добавляет следующую к уже полученным элементам. Конкретному экрану остаётся определить начальный индекс, запрос данных и способ вычислить следующий индекс. В интерфейсе NotificationListener отслеживает конец прокрутки и вызывает загрузку.

В руководстве Динко Маринаца есть схема слоёв, реализация поиска и фильтров и полный пример кода. Разбор предполагает знакомство с MVVM и репозиторием.
  • 👎 3
  • ❤ 1
Post #4741 1.02K
Как использовать @MainActor для интерфейса в Swift

@MainActor привязывает класс, метод, свойство или замыкание к глобальному актору, задачи которого идут в главном потоке. В конкурентном коде так компилятор проверяет контекст обновлений UI вместо ручных вызовов DispatchQueue.main.async.

В Swift 6.2 новые проекты Xcode 26 по умолчанию изолируют код приложения главным актором. Тяжёлые вычисления можно вынести из главного актора через nonisolated или @concurrent, чтобы не задерживать интерфейс.

В режиме Swift 5 остаётся ловушка: синхронный @MainActor-метод из неизолированного контекста может выполниться в потоке вызывающего кода. Swift 6 ловит большинство таких случаев при компиляции. Разбор SwiftLee сравнивает MainActor.run с Task { @MainActor in } и объясняет ограничения assumeIsolated.
  • 👍 1
Post #4740 1.1K
Как ловить визуальные регрессии в Android Compose с Paparazzi

Скриншот-тест рендерит компонент или экран и сравнивает снимок с эталоном. Paparazzi запускает такую проверку на JVM без устройства и эмулятора. Можно быстро прогнать разные экраны, но библиотека использует LayoutLib и наследует ограничения превью Android Studio.

В разборе показан цикл: подключить плагин, вызвать paparazzi.snapshot в JUnit-тесте, записать эталон через recordPaparazziDebug, затем сравнить кадр командой verifyPaparazziDebug. Отчёт покажет эталон, результат и различия.

Добавляйте проверку в CI как дополнение к другим тестам. Для задуманного изменения эталон перезаписывают; визуальную регрессию исправляют. Если снимков много, автор советует Git LFS, чтобы не раздувать Git-репозиторий.
  • 🎉 2
Post #4739 1.19K
Как отделить данные от интерфейса во Flutter с помощью репозитория

Репозиторий помещают в слой данных между источником и бизнес-логикой. Он вызывает REST API или базу данных, преобразует JSON в типизированные сущности и отдаёт их приложению. Виджеты не зависят от сетевого клиента и формата ответа, а изменение стороннего API исправляют только в репозитории.

В примере WeatherRepository задаёт получение погоды по городу, а реализация запрашивает OpenWeatherMap и разбирает ответ. В тестах сетевой код заменяют тестовым репозиторием. Абстрактный класс для этого необязателен: в Dart у каждого класса есть неявный интерфейс. Разбор Repository Pattern для Flutter сравнивает абстрактные и конкретные классы и показывает полный код приложения.
  • 🥱 3
  • ❤ 2
Post #4738 1.22K
Было: качаешь альбом через торрент трое суток, боишься выключить компьютер. Стало: включаешь трек в одно нажатие и не думаешь, где он хранится.

Между этими двумя точками — двадцать пять лет, которые SpaceWeb прошёл вместе с рунетом. Анкета к юбилею компании как раз про этот путь.
Post #4737 1.14K
Как найти причину утечки памяти в Android с LeakCanary

Утечка возникает, когда приложение сохраняет ссылку на уже ненужный объект. LeakCanary строит leak trace: цепочку сильных ссылок от неудаляемого корня сборщика мусора до удерживаемого объекта. По состоянию и жизненному циклу объектов инструмент сокращает список подозрительных ссылок.

В примере из статьи синглтон Application хранит TextView в списке. TextView через поле mContext удерживает уничтоженную MainActivity. Такая цепочка указывает, где искать причину: View добавили в долгоживущую коллекцию приложения.

В руководстве LeakCanary разложены четыре этапа: получить цепочку, сузить подозрения, найти ссылку, которая вызывает утечку, и убрать её. LeakCanary выполняет первые два этапа, а решение в коде остаётся разработчику.
square.github.io Fixing a memory leak - LeakCanary A memory leak detection library for Android
Post #4736 1.2K
Как Baidu переносила бизнес-логику iOS и Android на Kotlin Multiplatform

В приложении Wonder одинаковые правила отдельно реализовывали на Swift и Kotlin. Изменения приходилось синхронизировать между командами, а корректность проверять дважды. Связанный с логикой интерфейс также мешал повторно использовать код и писать модульные тесты.

Команда начала с общего слоя данных: объединила модели, REST-запросы, разбор JSON и кеш данных по ключу. Нативные интерфейсы iOS и Android сохранили. Позже часть интерфейсной логики перенесли на шаблон MVI для управления состоянием, а настройку модулей упростили собственными плагинами Gradle.

Подключение модуля добавляло 2 МБ из-за встроенной среды выполнения, а отладка общего Kotlin-кода для iOS сводилась к логам и замедлялась по мере роста проекта. Кейс Baidu показывает порядок внедрения и ограничения, которые стоит проверить на пилотном модуле.
Post #4735 1.2K
Как акторы Swift защищают состояние от гонок данных

Гонка данных возникает, когда потоки без синхронизации обращаются к области памяти и хотя бы один пишет в неё. Актор изолирует изменяемое состояние: снаружи его методы и свойства доступны через await, а компилятор проверяет синхронизированный доступ. Неизменяемые свойства можно читать напрямую.

Каждый await может приостановить код. Между двумя вызовами актор способен обработать другой запрос, поэтому связанные операции лучше объединять в одном методе. Для методов и вычисляемых свойств, которым нужны только неизменяемые данные, есть nonisolated: их вызывают без ожидания.

В разборе SwiftLee есть код до и после замены очереди с барьером на актор и объяснение изоляции. Граница подхода тоже обозначена: акторы уменьшают риск гонок данных, но состояния гонки всё ещё возможны.
Post #4734 1.29K
Как убрать нестабильность скриншот-тестов Paparazzi с Lottie

Paparazzi снимает Android-интерфейс через Layoutlib без эмулятора. Layoutlib обычно вызывают из одного потока, а приложение запускает фоновые задачи.

В нестабильном тесте Lottie загружала анимацию в фоне, а затем отправляла задачу через Handler. Одновременно Paparazzi перебирала карту очереди обработчиков. Добавление обработчика во время перебора вызывало ConcurrentModificationException и периодически роняло часть CI-прогона.

Обход для тестов: в методе @Before заменить LottieTask.EXECUTOR исполнителем, который запускает задачу в текущем потоке. Исправление в Layoutlib требует синхронизировать доступ к карте и её спискам. Код воспроизведения и вариант синхронизации есть в подробном разборе.
  • ❤ 1
Post #4733 1.25K
Как отделить загрузку данных от экранов на SwiftUI

Если экран сам запускает запрос, хранит результат и переключается между загрузкой, ошибкой и контентом, интерфейс смешивается с сетевой логикой. Swift by Sundell сначала показывает эту схему на ArticleView, а затем выносит загрузку и состояние в модель представления.

Дальше появляются общий LoadingState с четырьмя состояниями, протокол LoadableObject и универсальный AsyncContentView. Контейнер выбирает представление по состоянию источника, а экран только отрисовывает готовые данные.

Материал написан для Swift 5.3 и уже помечен архивным: архитектурный приём полезен, но API стоит сверять с текущим SwiftUI. В статье Swift by Sundell есть код всех трёх вариантов.
  • 👍 1
Older posts →

About this channel

How can I read @mobi_dev without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Мобильная разработка: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Мобильная разработка have?
Мобильная разработка (@mobi_dev) has 13.2K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Мобильная разработка know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →