EasySwift iOS🍏
Open in Telegram
Все самое интересное в мире iOS разработки 🧑🏻💻 Предложить статью или новость: @EasySwiftBot По всем вопросам обращаться к @itereznikov
Show more2 829
Subscribers
No data24 hours
-77 days
-1830 days
Data loading in progress...
Similar Channels
Tags Cloud
Incoming and Outgoing Mentions
---
---
---
---
---
---
Attracting Subscribers
September '26
September '26
+3
in 0 channels
August '26
+24
in 0 channels
Get PRO
July '26
+30
in 0 channels
Get PRO
June '26
+28
in 0 channels
Get PRO
May '26
+61
in 0 channels
Get PRO
April '26
+40
in 0 channels
Get PRO
March '26
+33
in 0 channels
Get PRO
February '26
+26
in 0 channels
Get PRO
January '26
+32
in 0 channels
Get PRO
December '25
+28
in 0 channels
Get PRO
November '25
+20
in 0 channels
Get PRO
October '25
+43
in 1 channels
Get PRO
September '25
+30
in 0 channels
Get PRO
August '25
+35
in 1 channels
Get PRO
July '25
+34
in 0 channels
Get PRO
June '25
+41
in 1 channels
Get PRO
May '25
+41
in 0 channels
Get PRO
April '25
+48
in 0 channels
Get PRO
March '25
+60
in 0 channels
Get PRO
February '25
+70
in 0 channels
Get PRO
January '25
+62
in 0 channels
Get PRO
December '24
+47
in 0 channels
Get PRO
November '24
+45
in 0 channels
Get PRO
October '24
+62
in 0 channels
Get PRO
September '24
+53
in 0 channels
Get PRO
August '24
+50
in 0 channels
Get PRO
July '24
+52
in 0 channels
Get PRO
June '24
+46
in 0 channels
Get PRO
May '24
+54
in 0 channels
Get PRO
April '24
+57
in 0 channels
Get PRO
March '24
+41
in 0 channels
Get PRO
February '24
+76
in 0 channels
Get PRO
January '24
+122
in 0 channels
Get PRO
December '23
+109
in 0 channels
Get PRO
November '23
+84
in 1 channels
Get PRO
October '23
+71
in 4 channels
Get PRO
September '23
+65
in 0 channels
Get PRO
August '23
+92
in 0 channels
Get PRO
July '23
+80
in 0 channels
Get PRO
June '23
+117
in 0 channels
Get PRO
May '23
+1 010
in 0 channels
Get PRO
April '23
+44
in 0 channels
Get PRO
March '23
+86
in 0 channels
Get PRO
February '23
+76
in 0 channels
Get PRO
January '23
+186
in 0 channels
Get PRO
December '22
+143
in 0 channels
Get PRO
November '22
+327
in 0 channels
Get PRO
October '22
+356
in 0 channels
Get PRO
September '22
+107
in 0 channels
Get PRO
August '22
+253
in 0 channels
Get PRO
July '22
+607
in 0 channels
| Date | Subscriber Growth | Mentions | Channels | |
| 07 September | 0 | |||
| 06 September | 0 | |||
| 05 September | 0 | |||
| 04 September | 0 | |||
| 03 September | 0 | |||
| 02 September | +2 | |||
| 01 September | +1 |
Channel Posts
Modern iOS Performance: Episode 2
⚠️ Переход на
Swift Concurrency и другие современные абстракции не делает приложение автоматически быстрее - они упрощают код, но могут невольно сериализовать параллельную работу, переместить тяжёлые вычисления на главный поток или скрыть расходы времени выполнения. Компилятор примет код, но это не гарантирует корректной модели конкуренции: важно явно понимать, кто запускает, отменяет и к какому состоянию имеет доступ асинхронная задача.
⚙️ Автор разбирает расходы абстракций - протоколы, type-erasure, actors, AnyView/AnyPublisher и т.п. - особенно на «горячих» путях (скролл, рендер, частые обновления). Цель - не убрать абстракции, а понять, где их стоимость платится и действительно ли это критично. Отдельно - влияние статической и динамической линковки, менеджеров зависимостей и модульности на время запуска; большой граф зависимостей часто скрыто тянет старт приложения.
🔴 Совет: контролируйте путь запуска, откладывайте всё лишнее, что не нужно для первого полезного экрана, явно обозначайте владельцев и границы асинхронной работы и проверяйте, где ваши удобные абстракции оказываются в “горячем” цикле - там имеет смысл измерять и оптимизировать.| 2 | How Do You Build a Mutex That Works with async/await ?
🔍 Автор столкнулся с задачей запретить одновременный запуск async метода и показал, почему ни actor, ни Mutex не подходят. Решение - библиотека TaskGate (AsyncGate и AsyncRecursiveGate): это асинхронный «турникет», который допускает только одну задачу внутрь и при этом безопасно позволяет await внутри секции.
❓ Внутреннее состояние - два состояния (.unlocked и .locked(queue)) и простой NSLock для защиты этих маленьких синхронных обновлений. Первая задача просто «заходит» и оставляет дверь закрытой; последующие регистрируют свою continuation как билет в очередь и «паркуются» без блокировки потока. Когда владелец выходит, он не открывает ворота всем сразу, а передаёт продолжение следующему - handoff, честная FIFO-очередь, никакой толкучки.
✔️ Этот подход подход даёт нужную семантику асинхронной взаимной исключённости и решает проблему priority inversion — при поддержке ОС библиотека эскалирует приоритеты ожидающих задач, прокидывая bump по очереди.
❌ Из минусов - AsyncGate не Sendable и предназначен жить в одном акторе (во избежание ошибок), а вход в тот же gate из той же задачи приведёт к дедлоку - для этого есть AsyncRecursiveGate. | 349 |
| 3 | 🧭 Podlodka iOS Crew: разработка с AI
С 14 по 18 сентября пройдет новый сезон Podlodka iOS Crew. В этот раз в центре внимания авторов конференции то, как AI меняет iOS-разработку.
Что ждёт участников:
🍏 Стратегия внедрения терминальных ИИ-агентов и MCP-интеграции в ежедневную iOS-разработку
🍏 AI как экзокостюм мобильного разработчика: harness, skills, CLI, orchestration, validation и evals
🍏 Знания о том, как запускать локальные модели на Apple Silicon
🍏 Готовые скрипты, которые можно забрать в свой проект: шаблон рабочего пространства агента, примеры скиллов и MCP, пайплайн от Jira-задачи до Merge Request.
И это ещё не всё! Подробности о сезоне смотрите на сайте, и там же есть билеты по early-bird цене.
👉 Билеты на Podlodka iOS Crew
А по промокоду swift_ioss получите скидку🎁 | 516 |
| 4 | Миллион частиц на iPhone: строим аттрактор Лоренца на GPU с Metal
👀 Автор показывает практический эксперимент: симуляция аттрактора Лоренца на сотнях тысяч частиц полностью на GPU с помощью Metal - расчёт через вычисляемые шейдеры, ping‑pong буферы и рендер одного буфера как point primitives. Главное архитектурное решение простое и рабочее: состояние частиц живёт только на GPU, CPU лишь обновляет uniforms и кодирует команды.
💡 Проходится весь путь от формулы и выбора интегратора (Euler, RK2, RK4) до деталей реализации: выравнивание структур между Swift и MSL, создание staging/двух приватных буферов, выбор размеров threadgroup, отрисовка точек, additive blending и избегание waitUntilCompleted.
✏️ Что стоит забрать из статьи про работе с металом:
➡️ храните в particle buffer только то, что нужно
➡️ подбирайте threadgroup по возможности pipeline
➡️ ограничивайте frameDelta для стабильности
➡️ профилируйте через GPU Frame Capture прежде чем упрощать симуляцию
➡️ если рендер дорогой — уменьшайте pointSize, particleCount или меняйте blending
➡️ для продуктовой версии делайте пресеты по GPU time | 500 |
| 5 | Private properties no longer break the memberwise initializer in Swift 6.4
🆕 В Swift 6.4 изменили правило синтеза memberwise инициализатора для структур: теперь свойства, которые менее доступны, чем максимально возможный уровень доступа и при этом имеют значение по умолчанию, исключаются из синтезируемого инициализатора.
❓ Что это значит на практике: если вы добавили приватное поле вроде cached id = UUID() с инициализацией, оно больше не «тянет вниз» доступность всего инициализатора — внешний код всё ещё может вызывать Post(title:…, body:…) без доступа к id. Компилятор сохраняет обратную совместимость: дополнительно синтезируется старый, более закрытый инициализатор, доступный в том же файле.
❗️ Важно:
➡️ приватное свойство без значения по умолчанию всё ещё остаётся в инициализаторе и делает его приватным
➡️ если все свойства приватные, поведение не меняется (инициализатор остаётся приватным)
➡️ изменение упрощает рефакторинг: можно добавлять приватные детали (кеши, идентификаторы) без ручной правки инициализатора | 659 |
| 6 | WebRTC on iOS in 2026, without building a video call
ℹ️ WebRTC - это не просто видео фреймворк, это реально рабочий P2P канал с обходом NAT и низкой задержкой. Автор крутит одно соединение между узлами и пять каналов данных: touch (быстро, без гарантий доставки), terminal (строго порядок и надёжность) и ещё три для команд, уведомлений и потоков логов. Благодаря разделению на каналы, мегабайты логов не мешают срочной команде отмены сборки.
Несколько полезных советов:
➡️ на каждую комнату должен приходиться один постоянный клиент сигналинга. Если будет несколько - будет дерганье: старый клиент кикает новый, новый кикает старый — вечная петля.
➡️ при временных проблемах сети делаем ICE‑restart - не рвём всю связь; если же сессию захватили с другого устройства (другой device id) - полное повторное соединение и старое устройство не лезет назад автоматически
➡️ шлите меньше мусора в списке адресов - без TCP, без локальных 192.168 и без .local. TURN учётки выдавайте краткоживущие через свой сервер - секреты в бинарник не встраивайте
➡️ В фоне iOS не гарантирует сохранение UDP соединения. Поэтому при переходе в фон лучше корректно закрыть соединение, а при возвращении приложения восстановить его заново | 624 |
| 7 | Как мы построили систему регрессионного UI-тестирования для iOS-приложения: XCUITest, mock backend и XcodeBuildMCP
🖥 Статья описывает практическую архитектуру для масштабируемой UI-регрессии в зрелом iOS‑проекте. Вместо попыток заменить XCUITest авторы строят инфраструктуру вокруг него: роботы (Robot Pattern) инкапсулируют работу с интерфейсом, launch arguments управляют стартовым состоянием приложения, а собственный mock‑backend с профилями отвечает за детерминированные серверные ответы. Такой подход переводит единицу регрессии с отдельного теста на воспроизводимый сценарий: начальное состояние + конфигурация backend + действия пользователя + ожидаемый результат
🔴 Важная часть - интеграция ИИ‑агента через XcodeBuildMCP, который автоматизирует рутинный поиск маршрутов и генерацию XCUITest на основе текстового сценария и набора роботов. Агент работает в ограниченном рабочем контексте, генерирует нативный тест, собирает и запускает его, но финальную проверку и принятие кода делает разработчик; CI остаётся зависимым только от нативных тестов. Дополнительно Mock Admin даёт удобный интерфейс для активации, временных изменений и просмотра журнала запросов, что упрощает воспроизведение и диагностику проблем без риска случайно поломать регрессию
ℹ️ Такой стек делает тесты короче, надёжнее и воспроизводимее - особенно для сценариев с retry, polling, push и deep link, где важны последовательность запросов и состояние сервера. Но нужно следить за синхронизацией mock‑профилей с реальным API (OpenAPI/контрактные тесты), чётко версионировать профили и держать правила генерации тестов в code review, чтобы ИИ‑генерация не создавала неожиданные зависимости | 664 |
| 8 | How to use SwiftData
Статья для тех, кто не знает про SwiftData 🤔
🔍 SwiftData - современная замена Core Data с нативным апи: вместо xcdatamodeld и ручных fetch запросов используются макросы @Model, @Relationship, @Transient и #Predicate. Модель - просто класс с @Model: все свойства сохраняются по умолчанию, вычисляемые помечают @Transient, уникальные ограничения - через #Unique, а enum хранится при Codable
⚙️ Контейнер создаётся на уровне приложения (.modelContainer(for:)), вьюшки получают ModelContext из окружения и вставляют/удаляют объекты, вызывая save() когда важна консистентность. В SwiftUI для выборок - @Query (автообновление), вне view - FetchDescriptor и modelContext.fetch(…); только для подсчета - fetchCount(_:)
Главные подводные камни: ➡️ id временный до первого save
➡️ всегда указывайте deleteRule и inverse в связях
➡️ предикаты поддерживают не весь Swift - некоторые вызовы либо не компилируются, либо падают в рантайме (например map/reduce, hasSuffix, сравнения вроде isEmpty == false). | 640 |
| 9 | NSTextTable in Swift
🆕 В iOS 27 UIKit добавили полноценные таблицы в составе атрибутированных строк - NSTextTable и NSTextTableBlock. Это не view‑таблица, а расширение rich‑text: таблица становится частью NSAttributedString, а не набором отдельный вьюшек.
Важные оговорки:
➡️ NSTextTable описывает структуру: число колонок, алгоритм компоновки (.automatic или .fixed), поведение границ и т.п.
➡️ Каждая ячейка - NSTextTableBlock с позициями и span (как rowSpan/colSpan в HTML)
➡️ Ячейки привязываются к параграфам через NSMutableParagraphStyle.textBlocks, затем стиль применяется к части NSAttributedString
➡️ Ячейкам можно задать padding, margins, borders, фон, мин/макс размеры, проценты или абсолютные величины
⚠️ Когда не нужно использовать - большие наборы данных, прокрутка/ленивая подгрузка, интерактивные таблицы или таблицы типа spreadsheet - для этого лучше UICollectionView/UITableView. | 708 |
| 10 | Instruments Flame Graph Introduction
🔍 Если вы не знали, что такое flame-граф в Time Profiler, то самое время узнать - откройте Call Tree и нажмите правую кнопку над деталями, чтобы включить граф. Если кнопки нет, выбранный инструмент это не поддерживает.
❓ Flame‑граф это стопки прямоугольников, каждый - функция в стеке; ширина показывает, сколько времени функция была в стеке. Верхние строки - системные точки входа, ваши функции чаще ниже и отмечены синим. Самые «тяжёлые» вызовы находятся слева.
ℹ️ Чтобы оставить только свой код включите Hide System Libraries в Call Tree; кликайте по прямоугольникам и двигайтесь стрелками; для чтения имён делайте зум: Option+клик и Option+прокрутка (или жест трекпада), Option+клик в пустом месте - вернуть масштаб. | 716 |
| 11 | No text... | 720 |
| 12 | Building Testable SwiftData Applications
👀 В статье - как правильно тестировать SwiftData в iOS проектах, и главный акцент делает не на проверке самого фреймворка, а на защите бизнес логики. Для обычных юнит тестов лучше брать in-memory store, чтобы тесты были изолированными, быстрыми и не зависели друг от друга.
⚠️ В статье хорошо показано, какие тесты почти не дают пользы: например, когда вы просто проверяете, что модель сохранилась и снова прочиталась из базы. Гораздо ценнее тестировать реальные правила приложения - запрет одинаковых названий бюджета, корректный расчёт расходов, остатка и других важных значений.
⚙️ Отдельно автор показывает, что сложную логику лучше выносить из View в отдельные типы. Тогда код проще поддерживать, а тесты писать легче. В конце есть интересная мысль про ResultsObserver в iOS 27: он помогает наблюдать изменения SwiftData вне SwiftUI и тестировать такие сценарии без лишней возни с интерфейсом.
😊 Признавайтесь - тестируете SwiftData? | 706 |
| 13 | Picture-in-Picture в iOS: от запуска до переключения контента
🔍 Статья - практичный гайд по PiP на iOS. Автор показывает, как запустить системное «плавающее окно», настроить жизненный цикл и переключать контент без разрывов. Главный посыл: PiP - сквозной системный механизм, который живёт в отдельном окне и требует правильной подготовки.
Что обязательно проверить:
➡️ AVAudioSession настроен на .playback/.moviePlayback и активен - без этого PiP не стартует
➡️ В Capabilities включён Background Modes -> Audio, AirPlay, and Picture in Picture.
➡️ AVPictureInPictureController хранится в сильной ссылке, иначе ARC удалит его до отрисовки
Как жить с PiP в приложении:
➡️ Делегат нужен для восстановления интерфейса и очистки после остановки.
➡️ События управления (пауза/перемотка) не приходят через делегат. На iOS 18+ используйте AVMetrics, на более старых - KVO/Combine по timeControlStatus у AVPlayer.
➡️ Переключение видео без закрытия PiP: либо replaceCurrentItem(with:) у AVPlayer, либо, если пересоздаёте плеер, обновите contentSource у контроллера. | 668 |
| 14 | Building a reusable API client with URLSession in Swift
🔍 Очередной взгляд на то, как собрать лёгкий API‑клиент на базе URLSession и async/await. Выделяются общие шаги любых запросов, а именно: построение URLRequest, выполнение через URLSession, проверка HTTP ответа и декодирование JSON - и предлагает вынести их в одно место (APIClient) чтобы не дублировать код по проекту.
Приводятся компактные типы:
➡️ Endpoint с путём
➡️ методом и заголовками
➡️ небольшая обработка ошибок (invalidResponse, invalidStatusCode)
➡️ методы для сборки запроса и отправки
➡️ пример декодирования модели
🖥 Можно еще выделить в качестве полезных советов:
➡️ конфигурация URLSession через URLSessionConfiguration для таймаутов и кэша
➡️ передача сессии в клиент для тестируемости
➡️ корректная проверка HTTPURLResponse (чтобы 404/500 не прошли незамеченными)
➡️ встроенная поддержка отмены через Swift concurrency (task отменяет запрос). В целом, можно взять как стартовую точку и расширить авторизацией, логированием и обработкой ошибок по бизнес‑логике. | 670 |
| 15 | An Even Closer Look at Protocols and Global Actors
❓ Как лучше задавать изоляцию @MainActor для протоколов в Swift — всей протоколу, отдельным требованиям или вовсе не ставить атрибут?
ℹ️ На примере протокола для показа ошибок автор сравнивает «whole‑protocol» (удобно и сокращает код, но раньше мешало конформить акторы) и «per‑requirement» (более гибко, явнее поведение).
⚙️ Не вешайте @MainActor автоматически - сначала подумайте, где реально нужна синхронная работа с UI. Для внутренних API удобно использовать per‑requirement изоляцию, а для публичных или простых случаев можно сделать протокол не‑изолированным и перенести @MainActor на конкретные реализации. Особое внимание уделите параметрам (например, колбэкам) - им может понадобиться свой атрибут @MainActor или объявление как Sendable. | 697 |
| 16 | Splitting Large SwiftUI Views in the Apple's way
🔍 Интересная статья, где рассказывают, что для производительности в SwiftUI важнее выделять отдельные структуры View с узкими входными данными, чем разбивать большой body на вычисляемые переменные или вспомогательные функции с @ViewBuilder. Когда меняется состояние, SwiftUI пересчитывает body самого внутреннего типа View, поэтому все вычисляемые поля внутри того же struct пересчитаются вместе - отдельный struct даёт собственную границу инвалидизации и может быть пропущен, если его входы не изменились.
❓ Что можно сделать (на примерах из статьи):
➡️ заменить private var section: some View на private struct SectionView
➡️ передавать только нужные данные (Bool, Double, модель)
➡️ выносить тяжёлые части интерфейса - карты, карточки завершения, сложные списки - в отдельные типы.
⚙️ @ViewBuilder остаётся полезным для локальной условной структуры (if/switch), он даёт читаемость и структурную идентичность веток, но он не создаёт новую границу инвалидизации и не решит проблемы с лишними пересчётами или потерей состояния при переключении веток.
🖥 Короткий чеклист для ревью кода:
➡️ если вычисляемое поле зависит от часто меняющегося state - выносить в отдельный View
➡️ не пытаться «симулировать» сплит через @ViewBuilder или вспомогательные модификаторы
➡️ предпочитать modifier(value ? a : b) вместо if-веток для одного view | 760 |
| 17 | Liquid Glass: A Field Guide to UIKit Compatibility Pitfalls
🖥 Если все еще не мигрировали на Liquid Glass на UIKit - статья для вас: практические проблемы адаптации UIKit на iOS 26, замеченные автором в реальном проект.
❓ Главные кейсы - кнопки навигации, таббар и взаимодействие с WKWebView. Для UIBarButtonItem с customView на iOS 26 наблюдались искажение размеров и исчезновение цветов: решение - полностью «изолировать» вью с явными constrain (ширина, высота и центр) или заменить UIKit вью на SwiftUI через UIHostingController; это в большинстве случаев восстанавливало и размеры, и цвет.
🔍 Немного про баги с новым API бейджей (иногда не обновляется - простой трюк: временно убрать и вернуть customView) и переносом порядка rightBarButtonItems (иногда помогает DispatchQueue.main.async или лучше - trailingItemGroups).
⚙️ Про UITabBarController и WKWebView: если вы динамически перестраиваете таббар во время закрытия модального контроллера, это может ломать интерфейс - ждущая окончания анимации dismiss решает проблему. При встраивании WKWebView стоит обязательно использовать viewport-fit=cover и env(safe-area-inset-*) в CSS, иначе контент может оказаться под таббаром (особенно при position: fixed).
ℹ️ Наконец, есть баги без простого решения (например, смещение Stepper при появлении клавиатуры), поэтому автор советует тестировать на каждой поддерживаемой версии iOS и по возможности следовать HIG - чем дальше вы уходитe от стандартов, тем больше вероятность странных ошибок. | 724 |
| 18 | Saving lives with enums
ℹ️ Статья показывает простую, но часто забываемую практику при работе с enum в Swift - не прятать случаи под default и не полагаться на прямое сравнение (==). Автор объясняет, что при добавлении новых кейсов компилятор не предупредит об уязвимых местах, если вы везде использовали default или ==. Это может привести к логическим ошибкам - в примере с мороженым человек с аллергией может получить опасный продукт.
✔️ Как одно из решений: делать «исчерпывающие» switch - явно перечислять все кейсы вместо default и переносить проверки в вычисляемые свойства или функции с exhaustive-switch. Тогда при добавлении нового кейса компилятор выдаст ошибку и вы вынуждены будете явно решить, как новый кейс обрабатывать. Это чуть более многословно, но даёт безопасность и явность. Можно также добавить правило в линтер, но это за пределами этой статьи.
⚠️ Если сомневаетесь - откажитесь от default и от частых == для enum, особенно если enum используется в логике принятия решений. Лучше перестраховаться, чем потом получить баг в проде… | 700 |
| 19 | Сейчас будет горячо: нагрев iOS-устройств как продуктовая метрика
Зачем собирать thermal‑метрику в iOS и как? (Картинка передает суть 🙂)
🔴 Вместо попыток мерить температуру в градусах автор предлагает использовать ProcessInfo.ThermalState - системную оценку теплового давления с четырьмя состояниями (nominal, fair, serious, critical). ThermalState нельзя перевести в градусы, но оно уже нормализовано между моделями и даёт понятный сигнал, когда система начинает троттлить I/O, снижать FPS или отключать периферию.
🔍 Читайте thermalState один раз перед регистрацией наблюдателя и логируйте изменения через thermalStateDidChangeNotification.
А также отправляйте события в аналитику с контекстом (модель, экран, уровень батареи, зарядка, длительность сессии и т.д.). Это дешёвая в реализации метрика (одно свойство + нотификация + событие), но даёт полезные дашборды:
➡️ распределение по состояниям
➡️ по моделям
➡️ по экранам
➡️ время до first serious
➡️ сравнение версий
➡️ связь с Crash Rate и FPS.
🔥 На её основе можно приоритизировать оптимизации, включать адаптацию под конкретные устройства и реализовать реактивную деградацию в рантайме.
let state = ProcessInfo.processInfo.thermalState
NotificationCenter.default.addObserver(
forName: ProcessInfo.thermalStateDidChangeNotification,
object: nil,
queue: .main
) { _ in
let newState = ProcessInfo.processInfo.thermalState
Analytics.track(thermalState: newState)
} | 730 |
| 20 | Introducing the Safari MCP server for web developers
ℹ️ Safari MCP‑сервер в бета‑версии Safari 27 и Safari Technology Preview 247 - это реализaция Model Context Protocol, которая позволяет LLM‑инструментам подключаться к окну Safari и получать реальную информацию о странице: DOM, сетевые запросы, скриншоты и консольные логи. Для iOS‑разработчика практическая польза такая: меньше ручных прогонов сценариев, быстрее проверка экранов после изменений, удобнее искать расхождения между ожидаемым и фактическим состоянием интерфейса, проще ловить проблемы с доступностью и состояниями форм.
❓ Можно использовать для некоторых кейсов:
➡️ упрощённая отладка без постоянного переключения между окнами
➡️ проверка совместимости в Safari
➡️ анализ производительности (navigation timing, загрузки ресурсов)
➡️ базовая проверка доступности
➡️ верификация состояний интерфейса (формы, потоки оформления заказа).
🖥 Запуск прост: установить нужную версию Safari, включить веб‑функции и удалённую автоматизацию, добавить mcp‑сервер в конфиг агента или выполнить одну из команд для Claude/Codex. MCP работает локально и не отправляет данные в Apple - дальнейшая судьба логов зависит от выбранного агента, поэтому используйте только доверенные инструменты. | 635 |
