Веб-версияОткрыть в Telegram
YYDC — Pizza Powered iOS

YDC — Pizza Powered iOS

@YoungDaCode · канал · Технологии · в индексе с 2026-07-19
243подписчиков
150постов в индексе
K
Kirill Smirnov
Ссылка
нажмите — покажем
🫠 Пока отдыхал, постил мало, но читать не переставал. Поэтому буду по-тихоньку "доставать из загашника". Автор в статье пытается сделать кэш. Ну не столько кеш, сколько упрощённую модель мира, в которой механизмы доступные из коробки начинают работать. Он берёт iOS-сборку и насильно приводит её к детерминированному виду: 1. генерирует umbrella SPM-пакет как единый build graph 2. приводит DerivedData к стабильным абсолютным путям 3. поверх этого строит свой slot-based кеш. После этого артефакты сборки «вдруг» становится переносимым: их можно zip-нуть и перекинуть между CI-раннерами, потому что внутри больше нет отличий в путях и случайных хешей. Но важно: - это не распределённый билд-кеш и не интеграция с Xcode. - это локальный кеш, который можно копировать, потому что автор сначала нормализовал весь проект. С инженерной точки зрения — решение тяжёлое и хрупкое. Это не то, что хочется тащить в прод. Зато как упражнение для насмотренности — отличное, имхо, конечно. Статья очень наглядно показывает, проблемы о которых мы уже общались ранее в разрезе tuist-а, из-за чего сложно сделать норм-кэш из коробки в iOS. P.S.: Напоминание. Xcode 26 compilation cache делает лучше, но не идеально. Все еще ждем "красоты" из коробки. #L #BuildCache #iOS #Tuist #xcode 👏
3 · 202 ·
V
Vlad Tkachenko
Ссылка
нажмите — покажем
😄 Combine, Async/Await, Actors Еще одна статья про сравнение инструментов распараллеливания работы. Каждый инструмент решает свою задачу (последовательные операции, реактивные потоки, и защита общего состояния соответственно), как их сочетать и какие типичные ошибки нужно избегать при проектировании реального iOS-приложения. Combine Фреймворк для реактивных потоков: публикация значений во времени, операторы трансформации (map, filter, debounce, flatMap, merge и т.д.). Идеален для live-streams (поиск с debounce, данные с датчиков, пользовательский ввод, непрерывные обновления). Async/await Предназначен для последовательных, линейных асинхронных задач (одиночные сетевые запросы, цепочки запрос >> обработка >> рендер). Читабельный код, простой поток обработки ошибок и отмены задач через try/await и throws. Actors Механизм изоляции состояния: гарантирует последовательный доступ к свойствам актора, устраняя гонки данных и необходимость ручных блокировок. MainActor используется для UI-связанного состояния. Есть ли паттерн выбора решения? - Если это одна асинхронная операция, то используем async/await. - Если это поток событий, то используем Combine. - Если есть разделяемое изменяемое состояние, к которому обращаются несколько задач, то используем actors. - Часто правильный вариантом будет комбинация: actor для хранения/защиты состояния, async/await для одиночных операций, Combine для подписки на потоки и реактивной логики. Какие могут быть ошибки в использовании? - Бессистемное смешивание Combine и async/await. Их совместное использование возможно, но лишние преобразования Publisher-AsyncSequence увеличивают сложность кода и накладные расходы. - Использование actors повсюду. Акторы дают безопасность, но имеют затраты на изоляцию. Не нужно превращать в actor каждый класс, только те в которых есть общее изменяемое состояние. - Игнорирование структурированной конкуренции. Вместо самостоятельного управления потоками лучше пользоваться TaskGroup/withTaskGroup
5 · 205 ·
K
Kirill Smirnov
Фотография
нажмите — покажем
🤖 Universal Links at scale — то, о чём часто вопрошают. Не плохая статья про то, как на самом деле работают Universal Links в iOS — не на уровне «добавь AASA и всё заведётся», а на уровне Apple CDN, кешей и деплоя. Внутри: - как iOS получает и кеширует apple-app-site-association через CDN Apple - почему обновления AASA могут “не приезжать” часами и что с этим делать - как валидировать, что именно сейчас видит Apple - какие есть стратегии безопасного деплоя изменений Из моего опыта Universal Links — одна из самых мифологизированных частей iOS (для обывателей): «почему не открывается», «почему открылось в Safari», «почему у одного работает, у другого нет». Эта статья как раз закрывает эти “магические” зоны и объясняет механику. Единственное, чего не хватает для полной картины — это тонкостей iOS-части, например: - невозможности / костыльности передачи данных через Universal Link при перходе в приложение после установки из App Store - различий поведения cold start / warm start / reinstall Но как разбор инфраструктурной стороны (AASA, CDN, валидация, деплой) - кайф. #L #UniversalLinks 👏
10 · 211 ·
Egor Mezhin
Фотография
нажмите — покажем
😅 Вслед за остальными черепашками медленно вылезаю из панциря после новогодних праздников. Решил начать с темы несложной, но полезной. Про Xcode File Templates большинство давно знает и использует, но статья натолкнула на мысль еще раз подсветить этот инструмент и напомнить, почему он действительно полезен в повседневной разработке. ✏️ Когда вы создаёте новый экран или фичу, почти всегда повторяется одно и то же: - импорты - базовая структура View - ViewModel/Reducer - Preview - тестовый файл где-то рядом Чаще всего это решается копипастом. Работает, но: - легко забыть что-то переименовать - появляются мелкие расхождения в стиле - растёт количество рутинных действий 📝 Как раз в этом случае и можно использовать File Template. Это пользовательский шаблон файлов, который появляется прямо в Xcode. Вы заранее описываете: - какие файлы создаются - какой в них код - какие значения Xcode подставляет автоматически А дальше Xcode сам создает нужные файлы. 🔸Из чего состоит шаблон: - один или несколько .swift файлов - TemplateInfo.plist - плейсхолдеры в коде Например: ___FILEBASENAME___ _FILEBASENAMEASIDENTIFIER_ При создании файла Xcode автоматически подставляет нужные значения. 🔹 Как создать файл из шаблона: 1. File → New → File… 2. Выбрать нужную категорию 3. Выбрать шаблон 4. Ввести имя 5. Получить готовые файлы в проекте Без копипаста и лишних шагов. 🔍 TemplateInfo.plist описывает поведение шаблона: - имя шаблона, которое вы видите в Xcode - описание - тип шаблона - список файлов, которые будут созданы Через него можно: - создавать сразу несколько файлов - указать, какие файлы открывать после генерации - управлять отображением шаблона в Xcode По сути, именно TemplateInfo.plist определяет, насколько шаблон будет удобен в реальной работе. ✔️ Где шаблоны особенно хорошо работают: - SwiftUI View + ViewModel - Feature (View + Reducer + Preview) - экраны дизайн-системы - сетевые запросы с DTO - тестовые файлы с общей структурой Особенно полезно, когда: - в проект
5 · 233 ·
🦾 Наткнулся на пост про mise — резонирует с моим опытом, поэтому мои мысли: Mise приносит апгрейды в повседневную работу с окружением. - убирает кучу неудобств, которые есть при ручной работе с brew, версиями SDK, средами и т.п.; - устраняет необходимость поддерживать несколько инструментов вроде rbenv, pyenv, nodenv и т.д.; - делает настройку окружения предсказуемой и декларативной. Впервые я всерьёз посмотрел на mise в контексте работы с Tuist — и понял, что это реально прикольная вещь для стабильного dev-env. У нас в iOS-проекте это уже работает так: 📌 bootstrap — главный sh скрипт для поднятия окружения проекта (mise, CocoaPods, Tuist, прочие зависимости) 📌 Ansible скрипты — для общей настройки рабочей машины (macos, settings, ssh, xcode, dev-tools и т.п.) Такой дуэт даёт: ✅ универсальность на всех машинах команды и на CI ✅ быстрое приведение к рабочему состоянию ✅ минимум “у меня работает, а у тебя нет” Если ещё не пробовали — настоятельно рекомендую погрузиться. Mise явно стоит внимания как альтернатива плурал-инструментам управления версиями и окружением. #L #mise #Dev #CI 👏
5 · 215 ·
E
Фотография
нажмите — покажем
😏 Ещё один пост на несложную тему от меня, чтобы проще и спокойнее вкатываться в рабочий процесс. На этот раз про Equatable и Comparable. Вещи знакомые, но на практике ими часто пользуются по инерции, не всегда задумываясь, чем они отличаются. 🔹 Equatable отвечает ровно на один вопрос: равны ли два значения между собой. struct User: Equatable { let id: Int let name: String } Теперь можно: • сравнивать user1 == user2 • использовать removeDuplicates() • помогать SwiftUI понимать, изменилось ли состояние Где это обычно нужно: • модели данных • state в SwiftUI • тесты Важно: Equatable ничего не говорит про порядок. Только одинаковые значения или нет. 🔹 Comparable нужен тогда, когда элементы можно упорядочить. struct Score: Comparable { let value: Int static func < (lhs: Score, rhs: Score) -> Bool { lhs.value < rhs.value } } После этого можно: • сортировать массивы • использовать min() и max() • работать с диапазонами scores.sorted() scores.max() Важный момент: если тип Comparable, он автоматически обязан быть Equatable. Если мы умеем сравнивать порядок, мы обязаны понимать равенство. 🔹 В проектах нередко встречается: • Comparable, хотя сортировка нигде не используется • сложная логика сравнения «на будущее» • протоколы, добавленные просто на всякий случай На практике это редко даёт пользу и чаще усложняет модель. 🍕 Equatable и Comparable решают разные задачи, и в большинстве случаев достаточно минимально необходимого протокола. Иногда полезно просто спросить себя: я хочу проверить равенство или действительно упорядочить данные? Ответ на этот вопрос часто делает модель и код вокруг неё заметно проще. #R #Swift #SwiftUI 👏
1 · 284 ·
S
Sergio Petrov
Ссылка
нажмите — покажем
😄Рубрика кликбейт или "потраченного времени жаль" Листал свой фид, искал вдохновение о чем бы написать в канал и нашелся, на первый взгляд, идеальный кандидат на первый пост в этом году от меня О чем: Swift заменил Objective-C не потому, что тот был стар, а потому, что developers were the bottleneck 🎯Какие тейки: • разработка была секретна  • в iOS 15.1 16 из 22 фиксов были связаны с управлением памятью = дорого для Apple (из-за регуляторных затрат) • в целом ошибки при работе с памятью стоили Apple $67 ярдов • последние фичи в Obj-C были как раз для совместимости с Swift 🚀В Swift Apple сняла значительную часть рисков с разработчиков (на самом деле с себя) и переложила на компилятор: • Снесла (почти) Message dispatch = меньше проверок в runtime • В целом система типов стала жестче • В Swift Concurrency отдали компилятору разгребать Data Races = убрали самый сложный тип багов • Синтаксис приведен ближе к модным Python/JS и тд = больше вкатунов 🤔 От себя В целом, история звучит складно, но • откуда тейк про 67 ярдов - не понятно, just trust bro • не припомню, чтобы по статистике от OWASP мобилки сильно страдали от memory management, как будто в топе были иные проблемы (можно вспомнить про Dirty-COW, но насколько она эксплуатируема в мобилках - инфы нет) • раз была серьезная проблема, то почему так мало персонала было привлечено к разработке и релиз состоялся только через 4 года? "Небизнесовый" подход какой-то, тот же Go за год-два сварили (чую "это другое", спорить не буду) ну и добило меня Java had solved memory safety with garbage collection — but the unpredictable pauses were unacceptable for iOS’s fluid 60fps animations как будто у дроид-коллег были большие проблемы с 60fps анимациями именно из-за сборщика мусора, напишите в комменты 🍿 По итогу ощущение такое... то-ли кликбейт, то-ли нейронка написала (длинных "—" много, да, это косвенно), грустно 😭 🍕А выводы то какие? А вот выводы автор делает как будто в отрыве от всей остальной статьи, они довол
1 · 264 ·
V
Vlad Tkachenko
Ссылка
нажмите — покажем
Ссылка
нажмите — покажем
😄 Что такое модульность и когда она нужна? Модульность это разделение кодовой базы на четко очерченные, изолированные единицы с явными границами ответственности. Каждый модуль имеет публичный интерфейс, скрывает внутреннюю реализацию и может эволюционировать независимо. Модульность нужна не всегда. Для небольших проектов и прототипов она часто создает лишние накладные расходы. В этом случае простота и скорость может быть важнее архитектурной чистоты. Но когда продукт стабилизируется и становится ясно, что кодовая база будет расти, модульность помогает управлять сложностью, задает границы владения кодом и предотвращает деградацию в тесно связанный монолит. Проектирование структуры до написания кода Архитектуру стоит продумывать до начала реализации, а не по ходу роста проекта. Простая диаграмма модулей помогает определить границы, проясняет зависимости, снижает количество реактивных решений позже. Начинать рекомендуется с базового слоя: общие модели данных, сетевой слой, фундаментальные сущности. Раннее формирование этого слоя снижает риск болезненных переделок в будущем. Три основные категории модулей 🛠️ Foundation-модули содержат общие модели, примитивы, инфраструктурные компоненты. Они не зависят ни от чего выше по иерархии и используются практически везде. Также они не должны содержать пользовательские сценарии. 🧰 Service-модули содержат переиспользуемую логику и сервисы. Они зависят от Foundation и используются фичами. Foundation-модули никогда не должны зависеть от Service-модулей, это нарушает иерархию. 🚚 Feature-модули содержат пользовательские сценарии (онбординг, оплата, профиль и т. д.). Они могут зависеть от Foundation и Services, но не должны зависеть друг от друга. Горизонтальные связи между фичами быстро разрушают архитектуру и возвращают монолитные проблемы. Модульность ради модульности Внедрение модульности как модного веяния без должного проектирования ведет к проблемам при которых возникают циклы зависимостей, универсальные сервисы,
9 · 226 ·
K
Kirill Smirnov
Фотография
нажмите — покажем
🤖 🔐 Нативный способ борьбы с фродом на iOS: DeviceCheck (App Attest) В iOS есть два системных механизма от Apple, которые реально помогают с анти-фродом — DeviceCheck и App Attest. Оба — клиентские фреймворки. Они работают на устройстве и генерируют криптографические доказательства. Сервер сам ничего «не проверяет» — он просто отправляет эти данные в Apple и уже по ответу решает, что делать дальше. 📱 DeviceCheck Позволяет понять, что запрос пришёл с реального устройства и пользователь не пытается подделать свою активность. - Выпускаем ключ для приложения на developer.apple.com - Клиент в рантайме получает deviceToken через DeviceCheck API - Сервер валидирует его через Apple и может читать/писать два бита состояния, которые Apple хранит для пары устройство + приложение (подписывая с помощью jwt). Типичные кейсы: - «один бонус на устройство» - пометить девайс как подозрительный - soft-ban без аккаунта 🔐 App Attest Решает другую задачу (аналогичную deprecated ручке v1/validate_device_token) — подтверждает, что запрос идёт от оригинального приложения, а не от модифицированного. - Добавляется новый капабилити - Получается ключ (создаётся внутри Secure Enclave, наружу не экспортируется) для генерации nonсe с бекенда - Генерируется обьект attestation на основе приватного ключа и nonce и отправляется на бекенд для дальнейших проверок - Далее с помощью приватного ключа и nonсe генерируются assertion для отправки на сервер и верификации приложения Application даёт сигнал, Apple — источник доверия, Backend принимает бизнес-решение. P.S.: Ну и как всегда в разрезе security - оговорки. Jailbreak - все сломает (улучшайте jailbreak-detection), SSL-pinning поможет повысить защиту, скрывайте секреты, используйте обфускацию и шифрование. #L #Security #AntiFraud #DeviceCheck #iOS 👏
11 · 311 ·
K
Kirill Smirnov
Ссылка
нажмите — покажем
🍟 Легкое и познавательное чтение перед выходными —————— 🤫 Особенности построения и развития дизайн-системы в мобильном приложении СберЗдоровья В разработке нередко встречаются ситуации, когда разные части проекта имеют различный внешний вид и поведение, что затрудняет поддержку, ведет к увеличению сроков выпуска обновлений и ухудшению качества продукта. Решением подобных проблем является дизайн‑система, которая обеспечивает единую библиотеку компонентов и строгие правила их использования, позволяя сократить время разработки, минимизировать расхождения между частями продукта и значительно облегчить дальнейшую работу над проектом. Наш братик и по совместительству Android‑разработчик из СЗ, в статье рассказывает, как строили мобильную дизайн‑систему на iOS и Android проекте на SUI и Compose, соответственно, и оптимизировали интерфейсы #L #DesignSystem #iOS #Android 👏
2 · 335 ·
K
Kirill Smirnov
Ссылка
нажмите — покажем
☝️ В модульных iOS-приложениях важно понимать как именно линкуются модули. Существует 3 типа линковки: • Static • Dynamic • Mergeable Почему это важно? Тип линковки напрямую влияет на: • модульность и управляемость архитектуры, • размер приложения, • скорость запуска. Хороший разбор с примерами — тут. Отдельно отмечу mergeable libraries. Tuist прямо говорит о cost of convenience, и я с этим полностью согласен: ➡️ mergeable почти всегда сложнее организовать, ➡️ сложнее явно контролировать и дебажить, чем осознанная и прозрачная логика линковки. Подход который использую я, и который сквозь время доказал свою пригодность и масштабируемость (под бинарные кеши всякие т.д. не страдая качеством): • staticForDeploy — все библиотеки статические, кроме тех, что шарятся с экстеншонами • dynamicForDev — всё динамика для комфортной разработки Вся логика механизма зашита в Tuist.ProjectDescriptionHelpers, дополняется оверрайдами в CocoaPods и SPM. Итог: быстрее старт приложения в проде, удобство разработки и контролируемая архитектура без магии. P.S.: Если интересно, чуть больше года назад рассказывал об этом подробнее. #L #Linkage #iOS 👏
19 · 267 ·
Vlad Tkachenko
Ссылка
нажмите — покажем
😄 Когда хочется и новый стек трогать и легаси сильно не шатать Если коротко, то тут статья, а тут макрос, который сгенерирует async/await обертки над старыми callback-based функциями. Если чуть подробнее, то главная мысль не переписывать всё сразу, а создать мост между старым API и новым с помощью continuations и Swift-макросов, которые генерируют обёртки автоматически. Если в вашем проекте сетевой слой и другие корные модули написаны через completion handlers, то полный рефакторинг повлечёт большой объём изменений, нагрузку на тестирование и риски для стабильности. Используя bridge-подход можно включить async/await, сохранив обратную совместимость, поддержать постепенную миграцию и при этом не тормозить развитие продуктовых фич. func info( for id: String, completion: @escaping (NetworkResponse<Response, BaseErrorResponse>) -> Void ) { let request = Action.getInfo(id: id) guard var url = pathProvider.createURL(type: request) else { completion(.failure(.urlNotFound)) return } let endPoint = RequestEndpoint( url: url, parameters: request.parameters ) networkClient.request(endpoint: endPoint, responseHandler: completion) } Добавляя withCheckedContinuation мы создаем мост между кодом, основанным на коллбэках, и современным миром асинхронности. Параметр continuation это наша связь с асинхронным контекстом. Для предоставления результата continuation.resume() нужно вызвать ровно один раз. Можно вернуть значение через resume(returning:) или ошибки через resume(throwing:), а также resume(with result: sending Result<T,E>) если вы используется тип Swift Result. func info( for id: String ) async -> NetworkResponse<Response, BaseErrorResponse> { return await withCheckedContinuation { continuation in info(for: id) { result in continuation.resume(returning: result) } } } CheckedContinuation: Включает проверки в рантайме для обнаружения ошибок, если мы возобновля
7 · 232 ·
K
Ссылка
нажмите — покажем
🦾 Новый open-source навык для SwiftUI и AI-агентов Если вы уже используете AI-агентов для генерации SwiftUI, то наверняка сталкивались с тем, что код получался компилируемым, но не вполне «идентичным» SwiftUI — неэффективные паттерны, странные навигации или обновления состояний. Многие инженеры отмечают, что AI-помощники часто не понимают тонкостей SwiftUI и генерируют почти SwiftUI, который приходится вручную править и рефакторить. В новой статье от Antoine van der Lee анонсирован SwiftUI Agent Skill — open-source навык для AI-агентов, который помогает писать, улучшать и рефакторить SwiftUI-представления по лучшим практикам Apple. 🔍 Что такое Agent Skills? Это пакеты с подробными инструкциями и контекстом по предметной области (в данном случае SwiftUI), которые AI-агент может «подгружать» и использовать при генерации/анализе кода, вместо того чтобы полагаться только на базовую модель. Такая система снижает количество повторяющихся ошибок и делает выводы агентов более осмысленными. 📌 В Skill есть подробные референсы по: • оптимизации изображений и layout-паттернам; • правильной композиции view; • управлению состоянием и производительности; • современным API и паттернам навигации. 💡 Это отличный шаг к тому, чтобы AI-агент не просто генерировал SwiftUI, а генерировал его правильно — с учётом архитектурных рекомендаций и практик сообщества. #L #AI #SwiftUI 👏
12 · 249 ·
Egor Mezhin
Ссылка
нажмите — покажем
😏 Хочу разобрать статью про переход на Observation в SwiftUI и напомнить, зачем вообще появился этот механизм и чем он отличается от привычного ObservableObject. Тема не новая, но на практике до неё доходят не сразу, особенно если в проекте уже есть устоявшийся подход к работе с состоянием. 🔹 Начиная с iOS 17 в SwiftUI доступен фреймворк Observation, который позволяет отслеживать изменения состояния без использования ObservableObject, @Published и Combine. Основная идея – упростить работу с состоянием и сократить шаблонный код. 🔹 Классический подход с ObservableObject работает, но имеет свои особенности: • необходимость явно помечать свойства как @Published • дополнительный синтаксический шум • риск забыть опубликовать изменения • привязка к Combine даже в простых сценариях Observation предлагает более прямой способ описывать наблюдаемое состояние. 🔹 На уровне кода вместо ObservableObject используется атрибут @Observable. Старый подход: class Counter: ObservableObject { @Published var value = 0 } С Observation: @Observable class Counter { var value = 0 } 🔹 Преимущества такого подхода: • Нет необходимости писать @Published, objectWillChange и вспомогательные конструкции. • Меньше риска ошибок, связанных с ручным управлением публикацией изменений. • Логика наблюдения находится ближе к самой модели. Пример использования: @Observable class TimerModel { var time: Int = 0 func tick() { time += 1 } } Использование во View: struct TimerView: View { @State private var model = TimerModel() var body: some View { Text("Time: \(model.time)") } } SwiftUI отслеживает изменения time и обновляет View без дополнительной настройки. 🔹 Где Observation особенно уместен: • простые ViewModel и модели состояния • логика, не требующая Combine • случаи, где ObservableObject использовался только ради обновления UI Следующие механизмы продолжают работать как раньше: • @State • @Binding • @EnvironmentObject Observation не заменяет
9 · 270 ·
K
Фотография
нажмите — покажем
🦾 Автоматика подъехала: Опыт Tuist-а, где Codex мигрирует проект на кодген и поддерживает кеширование. + Tuist превращает все это дело в skill 🛠️ 📦 Миграция Mastodon iOS 🎮 Первый skill — migrate #L #Tuist #AI 👏
19 · 3.1K ·
K
Kirill Smirnov
🤖 📡 Базовые протоколы клиент-серверного взаимодействия (без обратной связи) Хочется сделать серию постов по основам CS и system-design. Если будет отклик, масштабируем в mind-map. И начать хочется с сетевого взаимодействия. Когда мы говорим про клиент-серверные запросы в большинстве приложений, мы почти всегда имеем в виду модель request → response. Важно сразу зафиксировать: это не всегда про HTTP, хотя на практике часто выглядит именно так. В первом посте разберём основные стили взаимодействия, которые используются для однонаправленных запросов с ответом. 📌 Немного про транспорт: - SOAP — почти всегда поверх HTTP/HTTPS - REST — по определению строится поверх HTTP - GraphQL — чаще всего поверх HTTP, подписки через WebSocket (но об этом можно глубже, в другом посте) - RPC — не обязан использовать HTTP 👉 Поэтому корректнее говорить не «HTTP-протоколы», а API-стили / протоколы поверх разных транспортов. Небольшая затравка из практики: В бородатых годах я использовал Apache Thrift на Objective-C — тогда для меня это был "магический" опыт с RPC: отличный кодген, строгие контракты, минимум ручной работы. Это был классический пример RPC-подхода, задолго до хайпа gRPC, и он отлично показывал разницу между: - «я работаю с ресурсами» (REST) - и «я вызываю удалённые методы» (RPC) Детальнее про протоколы: 🔹 SOAP (Simple Object Access Protocol) Что это: Строгий протокол обмена сообщениями, основанный на XML и формальных контрактах (WSDL). Транспорт: почти всегда HTTP Когда применять: - корпоративные и интеграционные системы - среды с жёсткими требованиями к контрактам, безопасности и совместимости Почему: SOAP — это максимум формализма: строгая схема, строгие правила, минимум свободы. Цена — высокая сложность и избыточность. 📍 SOAP — это «корпоративный стандарт», а не инструмент скорости. 🔹 REST (Representational State Transfer) Что это: Архитектурный стиль, завязанный на HTTP, где всё крутится вокруг ресурсов и их состояний. Транспорт: HTTP. Когда применять: - CRUD-сц
5 · 247 ·
Kirill Smirnov
Ссылка
нажмите — покажем
🫡 ⚠️ Warning. Expensive. Experimental. В Claude Code появилась экспериментальная фича Agent Team. Что позволяет запускать виртуальную команду ИИ-сессий, которые работают параллельно над одной задачей, берут задачи из общего пула и могут общаться между собой напрямую. - можно распараллеливать работу по пуллу задач, - тимейты говорят друг с другом и сами решают, что делать дальше, - и могут критиковать друг друга, - полезно для сложных фич, исследований и коворкинга с ИИ. Но: 💸 дорого — каждый агент работает как отдельная сессия и "жжёт" токены, 🧪 экспериментально — фича отключена по умолчанию, поэтому, наверное, пока стоит осторожно. #L #AI #Agent #Team 👏
5 · 218 ·
Фотография
нажмите — покажем
😏 Снова громкий заголовок – «Combine умер?», решил коротко разобрать статью и понять причину хайпа. Повод - system prompt внутри Xcode AI, где есть рекомендация избегать Combine и предпочитать async/await. В system prompts Xcode есть строка: “Avoid using the Combine framework and instead prefer … async and await” Репозиторий с prompt’ами: https://github.com/artemnovichkov/xcode-26-system-prompts Это не документация Apple, а рекомендация для генерации нового кода. Но направление развития технологий читается довольно явно. Apple уже несколько лет двигает стек в сторону async/await, Task, Actor и AsyncSequence. Они лучше встроены в язык, проще читаются и требует меньше шаблонного кода. Новые API чаще строятся вокруг concurrency-модели. Combine никуда не делся. Он не deprecated, не удалён из SDK и используется в продакшене. Срочно переписывать существующий код смысла нет, но, очевидно, дефолтный выбор для нового async-кода сместился в сторону Structured Concurrency. #R #Swift #Concurrency #Combine 👏
2 · 221 ·
K
Ссылка
нажмите — покажем
Вечернее-занимательное чтение. Пишет iOS разработчик с опытом, обзор на пост от iOS разработчика с опытом. 😅 Многие часто говорят про work-life balance, выгорание и т.д. И по-моему для офисных работников и в т.ч. разработчиков это действительно важно. Иногда мало-активный образ жизни, иногда дефицит прогулок и солнца могут приводить к утомлению и моральному, и физическому, особенно, на фоне большого количества интеллектуальной активности на работах. Как-то после тяжёлой тренировки в зале у меня «поехала» спина. Итог — несколько месяцев лечения грыжи у очень сильных врачей по резорбции. Многое узнал про восстановление, но один мотив шёл через всё лечение красной нитью: витамин D в нормальных (иногда ударных) дозах реально ускоряет заживление, снижает воспаление и положительно влияет на самочувствие в целом. Теперь про пост и занимательные выводы по географии, и почему большинству не хватает витамина D. • Нью-Йорк ≈ 40,7° северной широты (место жительства автора) • Москва ≈ 55° • Астрахань ≈ 46° (моя родина) Исследование которое дает автор: Чем дальше от экватора — тем хуже коже удаётся синтезировать витамин D из солнца. Зимой в Москве UVB почти нет вообще. В Нью-Йорке солнца больше чем в МСК, сезон длиннее, но зимой дефицит тоже обычное дело. В Астрахани лучше, но в зимнее время, далеко не идеально. Отсюда и реальность: в Нью-Йорке есть проблемы, в МСК будет и подавно (с Астраханью сравнивать сложнее, солнца больше, но если верить статье про "усвоение", количество != качество). Мне врачи рекомендовали ударные дозы витамина D в день, для коррекции дефицита — и судя по всему, это распространённая практика, особенно осенью и зимой. Имхо, с дозировкой, конечно, лучше не гадать, а сдавать анализы и обсуждать с врачом. Если коротко: меньше солнца → меньше витамина D → хуже восстановление, иммунитет и общее самочувствие. А мы тут живём не на экваторе. #L #WorkLife #Health #Balance 👏
1 · 300 ·
E
Egor Mezhin
Фотография
нажмите — покажем
😏 Разберём разницу между some View и AnyView в SwiftUI. Тема не новая, но споры о правильном использовании периодически возвращаются. Коротко: some View сохраняет конкретный тип View на этапе компиляции. AnyView стирает тип и оставляет только «какой-то View» на этапе выполнения. Когда мы пишем: var body: some View { Text("Cowabunga") } Мы говорим компилятору: тип конкретный и известен, но имя типа скрыто. SwiftUI при этом: - строит статическое дерево типов - может оптимизировать diff - лучше отслеживает identity View - эффективнее обновляет UI А с AnyView: AnyView(Text("Cowabunga")) Мы теряем информацию о реальном типе и часть работы переносится в runtime. SwiftUI больше не знает: - какая структура View внутри - как оптимизировать обновления 🍕 Классический пример func content(isLoggedIn: Bool) -> some View { if isLoggedIn { return HomeView() } else { return LoginView() } } Компилятор ругается, потому что возвращаются разные типы. Можно быстро пофиксить так: func content(isLoggedIn: Bool) -> AnyView { if isLoggedIn { return AnyView(HomeView()) } else { return AnyView(LoginView()) } } Работает, но ухудшает оптимизации SwiftUI, да и ревью вряд ли пройдет. 😅 Нормальный SwiftUI-подход - использовать ViewBuilder. @ViewBuilder func content(isLoggedIn: Bool) -> some View { if isLoggedIn { HomeView() } else { LoginView() } } SwiftUI создаёт: ConditionalContent<HomeView, LoginView> И сохраняет типовую информацию для оптимизаций. Когда AnyView действительно нужен: - массив разных View - runtime injection View - API, где нельзя использовать generics Например: let cells: [AnyView] = [ AnyView(ProfileHeaderView()), AnyView(SettingsRow(...)) ] 🍕 Можно сформулировать простое правило: Если SwiftUI может знать тип на этапе компиляции → используем some View. Если тип появляется только во время выполнения → используем AnyView. AnyView не зло, но его легко начать использоват
10 · 274 ·
K
Kirill Smirnov
Ссылка
нажмите — покажем
☝️ 📦 Размер приложения — это не просто цифра в App Store Размер приложения напрямую влияет на: - конверсию в установку (особенно в регионах с мобильным трафиком), - время загрузки и first launch, - обновляемость (пользователь чаще откладывает “тяжёлый” апдейт), - хранение на устройстве. Исторически порог в ~200 МБ считался психологическим и сетевым барьером — при крупных загрузках. App Store, например предлагает переходить на Wi-Fi. Даже несмотря на изменения лимитов, сам эффект остаётся: чем тяжелее билд, тем выше friction. Недавно я интегрировал в нативное iOS-приложение Flutter-модуль. И это автоматически поднимает целый пласт инженерных вопросов: 🧩 Flutter inside native: что пришлось анализировать 1️⃣ Dependency resolution - transitive зависимости (резолв общих нативных SDK) - влияние flutter-плагинов на iOS/Android-проект - корректную сборку в release profile 2️⃣ Оптимизацию release-сборки - оптимизации Flutter.framework и App.framework (термины flutter) - в том числе удаление неиспользуемой функциональности 3️⃣ Бинаризацию Flutter-модуля - сборка в xcframework - кэширование артефактов - минимизация пересборки нативного проекта - влияние на CI и локальный DX Отдельная боль — время сборки. Flutter внутри iOS может существенно увеличить clean и incremental build, если не выстроить правильную стратегию доставки и кэширования. В целом по тех стеку для оптмизаций flutter проекта, можно тут почитать. 🏗 Но оптимизации — это не только Flutter. Мы давно системно работаем с нативным стеком: 🔹 On-Demand Resources (ODR) - Подгружаем тяжёлые ассеты по требованию. 🔹 Модуляризация - изоляция фич - переиспользование кода - контроль зависимостей 🔹 Работа с ресурсами - поиск дубликатов и больших ассетов - анализ неиспользуемых ассетов - контроль веса .xcassets - внутренняя аналитика через скрипты и graphana 🔹 App Thinning - понимание slicing - корректная работа с architectures - оптимизация universal vs device-specific бинарей 🔹 App Store Connect аналитика позвол
4 · 355 ·
K
Kirill Smirnov
Фотография
нажмите — покажем
☝️ В прошлом посте мы говорили про клиент-серверное взаимодействие: API, REST, запрос-ответ. Но прежде чем идти дальше (обсуждать двунаправленность), хочется сделать шаг вниз по стеку. Потому что REST и прочее - это архитектурные стили. А под ними живут транспорты и сетевые протоколы. Давайте разбираться. С чего всё началось — TCP и UDP (транспортный уровень): Когда два компьютера обмениваются данными, они делают это через транспортный протокол. 1️⃣ TCP — «передать всё и правильно» TCP появился в 70-х. Его цель — гарантировать доставку данных. - следит за порядком пакетов - подтверждает получение - переотправляет потерянные - регулирует перегрузку сети Это надёжно. Но за надёжность приходится платить задержками. Передача фрагметов данных - сложный процесс и достоин отдельного поста, на тему. Но, базово, из-за передачи пакетов и их согласования может возникать проблема - head-of-line blocking (если один сегмент потерялся — остальные ждут). 2️⃣ UDP — «передать быстро» UDP появился примерно тогда же, но философия у него другая. Он просто отправляет пакет. Без гарантий: - дошёл ли - в каком порядке Зато: - минимум задержек - минимум оверхеда Поэтому UDP любят там, где важнее скорость, чем идеальная надёжность: игры, голос, видео. 3️⃣ Дальше появился HTTP (прикладной уровень) Когда понадобился стандарт для веба, поверх TCP построили HTTP. GET, POST и т.д. запросы с примитивами вроде header, body и т.д. 👨‍🦳 HTTP/1.1: запрос → ответ. - каждый запрос зависел от предыдущего - соединения открывались и закрывались - производительность была далека от идеала (в т.ч. из-за текстового формата передачи данных) Но для 90-х этого было достаточно. 👷‍♂️ HTTP/2 — попытка ускорить веб. Спустя почти 20 лет стало ясно, что HTTP/1 не справляется. - стал бинарным - добавил мультиплексирование (чтобы решать head-of-line blocking на уровне HTTP) - позволил нескольким запросам идти параллельно в одном соединении Это серьёзно ускорило загрузку страниц. Но есть нюанс. HTTP/2 всё ещё раб
10 · 581 ·
K
Kirill Smirnov
Ссылка
нажмите — покажем
☝️ 🚀 Как MCP-аналитика помогает AI-агентам кодирования принимать более «осознанные» решения AI-агенты всё чаще используются для помощи в разработке кода: автоматический code review, рефакторинг, автогенерация тестов и т.д. Но что если дать агентам не только доступ к самому коду, но и к данным о продукте, пользователях и эффективности фич? 📊 Вот статья, об использовании MCP для оптимизаций Rocket-Sim от SwiftLee. Кратко: 🔹 AI обычно принимает решения только на основании синтаксиса и семантики кода. 🔹 MCP интегрирует контекстные данные: метрики использования, показатели конверсий, результаты A/B-тестов и др. 🔹 Решения становятся не только технически корректными, но и бизнес-ориентированными. 💡 Что это даёт в практике разработки: ✔️ AI может приоритизировать решения не только по сложности кода, но и по влиянию на KPI. ✔️ Предложения по оптимизации функциональности учитывают реальные пользовательские данные. ✔️ Улучшается связь между агентом и аналитикой продукта. #L #AI #MCP 👏
5 · 776 ·
V
Vlad Tkachenko
Ссылка
нажмите — покажем
😄 Статья CoordinatorKit 2.0: Production-Ready SwiftUI Navigation это пример честного разбора автором своих же ошибок. Можно даже сказать, пост-мортем. В противовес многочисленным “hello NavigationStack”, в ней хорошо объясняется, почему нативные SwiftUI-паттерны ломаются и даёт идеи, которые можно заимствовать даже без внедрения фреймворка или использовать как основу собственной навигационной архитектуры. На самом деле сделать фреймворк навигации, который будет удобным для использования и гибким для переиспользования под разные продуктовые кейсы это невероятно сложная задача. В больших проектах никуда без диплинков, сложных навигационных кейсов типа логин/логаут или внезапных кросс-фичовых переходов. Отдельного внимания заслуживает обработка жестов вроде смахнуть/свайпнуть экран, а точнее запретить это сделать для отдельных продуктовых случаев. Между первой и второй версией фреймворка виден невероятный разрыв. Аналогично, первая статья выглядит как наивная попытка сделать все легко, чисто и по правилам паттерна. А вторая статья это уже полноценный инструмент, набравший силы, повидавший требования и изменчивость продакшна. Топ "неожиданных" инсайтов: ❌ SwiftUI navigation не production-ready из коробки. 🍋 Достаточно больно жить без контроля над жестами, над root-экраном и над состоянием стека. 🐸 Coordinator-паттерн остаётся актуальным, но должен быть интегрирован глубже, должен быть concurrency-safe и должен перехватывать жесты, а не реагировать пост-фактум. ✈️ Навигация, по своей сути, ближе к бизнес-логике, чем к деталям UI. 📎 GitHub: CoordinatorKit #D #Arch #Navigation #Coordinator #SwiftUI 👏
8 · 910 ·

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем