fa
Feedback
YDC — Pizza Powered iOS

YDC — Pizza Powered iOS

رفتن به کانال در Telegram

Young Da Code 👨‍💻 Первый командный дайджест о мобильной разработке 🍕

نمایش بیشتر
247
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+27 روز
+430 روز
آرشیو پست ها
🦾 Наткнулся на пост про 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 👏

😅 Вслед за остальными черепашками медленно вылезаю из панциря после новогодних праздников. Решил начать с темы несложной, но
😅 Вслед за остальными черепашками медленно вылезаю из панциря после новогодних праздников. Решил начать с темы несложной, но полезной. Про 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 - тестовые файлы с общей структурой Особенно полезно, когда: - в проекте есть устоявшаяся архитектура - важно соблюдать единый стиль - в команду приходят новые разработчики 🍕 Почему полезно использовать шаблоны: - меньше рутинных действий - меньше ошибок от копипаста - единая структура по проекту - проще поддерживать кодовую базу - быстрее старт новых фич 🍕 Xcode File Templates – простой и уже встроенный инструмент, который легко недооценить. Но при регулярном использовании он заметно упрощает повседневную работу и помогает поддерживать аккуратную и предсказуемую структуру проекта. #R #Xcode #Templates 👏

🤖 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 👏

😄 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 для безопасного параллелизма. Какие выводы можно сделать? Swift Concurrency не обязует выбирать одну технологию: async/await, Combine и actors дополняют друг друга. Правильный выбор инструмента повышает читаемость, производительность и безопасность приложения, а неправильный может свести преимущества к нулю. 📎 Mastering Swift Concurrency: When to Use Async/Await vs Combine vs Actors #D #Swift #Concurrency #Async #Combine 👏

🫠 Пока отдыхал, постил мало, но читать не переставал. Поэтому буду по-тихоньку "доставать из загашника". Автор в статье пытается сделать кэш. Ну не столько кеш, сколько упрощённую модель мира, в которой механизмы доступные из коробки начинают работать. Он берёт 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 👏

😄 Combine vs Async/Await В долгоживущих проектах часто возникают проблемы с инструментами и архитектурами. Они имеют свойство накапливаться и перемешиваться. Старый код где-то на completion handlers, где-то на Promises, в старых вьюмоделях используется RxSwift, в относительно новых используется Combine, совсем новый код пишется на Async/Await. В результате мы имеем проект, который сложно читать, сложно дебажить, выше когнитивная нагрузка, больше технического долга. Конечно же, проблема кроется не в самих инструментах, а в отсутствии единого подхода к подбору инструмента под задачу. В какой-то момент мы решили отказаться от зависимости на RxSwift и начали использовать Combine, а замыкания и промисы потихоньку стали переводить на Async/Await. Кажется, здесь все однозначно и понятно. Но что же выбрать между Async/Await и Combine? Чем они отличаются концептуально? 🔹Async/Await это языковая модель структурированной конкуренции, встроенная в Swift. Она позволяет писать асинхронный код в линейном, последовательном стиле, максимально близком к синхронному. - Структурированная конкуренция. - Последовательный, линейный код. - Легко читать как синхронный. - Отлично ложится на модель «запрос → ответ». Не сахар над completion handlers, а другая модель мышления, ориентированная на понятный контроль потока выполнения. 🔸Combine это фреймворк для реактивного программирования. Работа происходит не с одиночными результатами, а с потоками значений во времени. - Реактивная парадигма. - Работа с потоками значений во времени. - Композиция, chaining, операторы (map, flatMap, retry, combineLatest). - Подходит, когда данные изменяются непрерывно. Не просто асинхронность, а реактивная архитектура. Как осуществляется обработка ошибок и отмена задач? 🔹В Async/Await ошибки пробрасываются через throw, отмена через Task, поведение более очевидное. 🔸В Combine ошибки это часть stream’а, отмена через Cancellable, логика рассредоточена по цепочке операторов. Почему нетворкинг это особый случай? Большинство сетевых операций по своей природе не реактивны: - один HTTP-запрос; - один ответ; - декодирование данных; - возврат результата или ошибки. 🔹Async/await в этом контексте короче, проще, легче тестируется, проще обрабатывает ошибки через try/catch. Для сетевого слоя это даёт async/await преимущество в предсказуемости и прозрачности логики. 🔸Для такого сценария Combine часто избыточен, добавляет ненужную сложность, ухудшает читаемость. С другой стороны Combine будет правильным выбором, если есть: - WebSocket; - live-updates; - continuous streams данных; - сложные зависимости между несколькими источниками данных; - когда UI напрямую подписывается на поток изменений. То есть там, где данные живут во времени, а не приходят один раз. Какие выводы можно сделать? Плохая идея использовать Combine и Async/Await вперемешку в одном сетевом слое. Лучше выбрать одну модель асинхронности для нетворкинга, чаще всего это будет Async/Await. Сombine стоит использовать выше по стеку (например, во ViewModel), если он нужен для реактивного UI. Combine и Async/Await не конкуренты, а инструменты для разных задач. 📎 Combine vs Async/Await: Choosing the Right Concurrency Model for Networking #D #Swift #Concurrency #Async #Combine 👏

😋 Безопасность Codex в VS Code — продолжение Если вы используете Codex в VS Code, важно осознанно управлять тем, какой контекст он видит. Особенно если в проекте есть секреты. Если секреты нужно спрятать от Codex, есть несколько рабочих вариантов: 1. Ограничить контекст через workspace. Настройте исключения в: • .vscode/settings.json, или • .code-workspace (лучше, если вы храните его в репозитории) ✅ Исключайте папки с секретами через files.exclude и search.exclude. Это снижает вероятность того, что файлы попадут в индекс и контекст Codex. 2. Вообще не хранить секреты в репозитории Лучший вариант с точки зрения безопасности: • secrets вне repo, • .env вне workspace, • CI/CD variables или secret manager. Это защищает не только от Codex, но и от любых IDE-расширений и автоматизаций. Дополнительные базовые рекомендации: • открывайте в VS Code только нужные модули проекта, а не корень монорепы; • не открывайте файлы с секретами вручную; • ограничьте сетевой доступ в настройках Codex; • используйте sandbox / manual approval для действий агента. Официальная документация по безопасности Codex #L #AI #Security #Codex #VSCode 👏

🍕 Хочется потихоньку выходить из новогоднего вайба и начинать набирать тонус и жизненный и рабочий. И начать год хочется с первой статьи — и снова про AI-кодинг. Похоже, ничего не предвещает, что темой года станет что-то другое. И, честно говоря, она хорошо резонирует с моим личным опытом за последний год. В статье описывается опыт разработчика, который всецело использует AI-инструменты в ежедневной работе и заметно изменил за их счёт и стиль, и темпы разработки. Пару мыслей, о которых мы уже не раз писали, но которые за этот год только усилились: Модели стали слишком умными, чтобы жить по старым правилам. Куча документации, отдельный промт-инжиниринг — всё это постепенно уходит. В большинстве случаев ты просто просишь сделать то, что нужно, и модель делает. Единственный нюанс: в новых проектах всё по-прежнему сильно выигрывает, если правильно дать старт архитектуре и сразу же вместе с AI сформулировать Agents.md. Инструментов становится всё больше, и выбор должен идти от задачи. Но если честно — OpenAI и Codex сейчас топ из топов. Почти все исследования сходятся в одном: GPT-5.2 — имба. Использование топовых LLM вместо локальной инфры неимоверно бустит качество. Да, возможно, со временем баланс сместится. Но точно не в этом году. Имхо. P.S. Моё текущее комбо для кодинга: xcodebuild MCP + Agents.md + Codex + VS Code — лучшее, что сейчас есть для написания кода. Ограничения контекста, к сожалению, всё ещё боль для Codex - нет поддержки .ignore файла аля .claudeignore. Думаю, все таки, в этом году мы должный прийти к единому .aiignore. Очень жду, что в 2026 Codex подтянут именно эту часть. #L #AI #MCP #iOS 👏

😏 Использование семантического версионирования (SemVer) — важный шаг к осознанному выпуску продуктов. SemVer — это не просто
😏 Использование семантического версионирования (SemVer) — важный шаг к осознанному выпуску продуктов. SemVer — это не просто набор чисел, а коммуникационный инструмент, который помогает команде, QA, бекенду и поддержке быстро понять, что произошло в конкретном релизе. Основная форма выглядит как: MAJOR.MINOR.PATCH Где: MAJOR — большие изменения или breaking changes. MINOR — новые функции без нарушения совместимости. PATCH — исправления багов и мелкие улучшения. Кроме базовых чисел семантика спецификации позволяет использовать метаданные через + и - например: 1.2.3+build45 Метаданные могут включать: номер пайплайна сборки тип сборки (например, QA, backend, экспериментальный билд) любые служебные данные, которые важны для внутренней идентификации Такие метки снимают массу вопросов при диагностике проблем и автоматически улучшают трассируемость между клиентом и бекендом. Полезные эффекты от SemVer: - Чёткое понимание, что изменилось (баг-фикс vs новая функция vs breaking change). - Упрощённое взаимодействие между командами. - Возможность строить логику QA/релизов на основе версии (alpha, beta, rc, build-meta). - Меньше вопросов у поддержки и аналитиков при разборе инцидентов. Вывод: если вы ещё не используете SemVer + метаданные в своих мобильных релизах — это однозначно стоит внедрить. #L #semver 👏

😄ARC, что внутри? Казалось бы, тема пройдена вдоль и поперек, однако на технических интервью я периодически встречаю недопонимание принципов работы ARC даже у опытных разработчиков ⚡️Самый важный момент:
ARC "живет" только при компиляции
Он не отслеживает объекты в рантайме, не решает, когда освобождать память. Его задача - вставить в скомпилированный код вызовы функций, которые при MRC в Objective-C разработчик расставляет самостоятельно: 👉 objc_retain(ptr) - увеличивает счетчик ссылок объекта 👉 objc_release(ptr) - уменьшает счетчик 👉 objc_autorelease(ptr) - отложенное уменьшение счетчика, сегодня редкий кейс, об этом чуть ниже Роль рантайма же - слепое исполнение инструкций. Если счётчик достигает нуля, объект немедленно деаллоцируется: вызывается deinit, освобождаются stored-свойства, память возвращается в кучу. Что до счётчика ссылок - он хранится в заголовке объекта в куче и создаётся при аллокации объекта. Из Swift-кода доступа туда не получить 🤔 Что по autorelease? Используется редко, но стоит упомянуть в контексте autoreleasepool. ARC вставляет autorelease только тогда, когда на этапе компиляции не может точно определить момент окончания владения объектом: 👉 Границы Swift ↔ Objective-C 👉 Объекты с атрибутом @autorelease Важный момент: autorelease не откладывает деаллокацию. Он откладывает выполнение release в конце блока autoreleasepool, итерации runloop'а или при завершении потока Именно поэтому autoreleasepool внутри циклов так важен для управления памятью. Без него множество больших объектов будут накапливаться в пуле до конца итерации runloop'а, вызывая скачок потребления памяти Итоговая модель выглядит так: 1️⃣ Swift-код 2️⃣ ARC на этапе компиляции вставляет вызовы retain/release/autorelease 3️⃣ Рантайм аллоцирует объект с заголовком 4️⃣ Retain → увеличивает счётчик. Autorelease → добавляет объект в пул (счётчик не меняется) 5️⃣ Пул завешается → выполняются release для всех объектов в пуле 6️⃣ Если счётчик == 0 → немедленная деаллокация. 💫 Надеюсь, сегодня мне удалось повысить понимание этого процесса: что решает компилятор, что слепо исполняет рантайм и где ответственность переходит к разработчику 📎 Что почитать? Постарше Посвежее Очень старая дока по ObjC, но многое актуально и для Swift #iOS #Swift #ARC #MemoryManagement #Performance 👏

😒 Claude Code + XcodeBuildMCP + xcodemake. Попытка сделать быстрые инкрементальные билды для AI, рядом с xcodebuild. Как это работает: xcodemake сначала прогоняет обычный xcodebuild, анализирует его и генерирует Makefile. Дальше при повторных сборках компилируется только изменённый код (без ресурсов и ассетов). За счёт этого повторные билды могут быть заметно быстрее. Важно понимать ограничения: - это экспериментальная фича - инкрементальность касается только кода, любые изменения ресурсов, настроек проекта и т.п. легко приводят к необходимости возврата к xcodebuild - магии уровня Bazel тут нет, это скорее аккуратный хак поверх существующих инструментов Сам XcodeBuildMCP — это MCP-сервер, который даёт AI доступ к Xcode: сборки, схемы, симуляторы, девайсы, discovery-проекта и т.д. Есть конфигурация: можно включать/выключать инкрементальные билды, ограничивать доступные workflow, настраивать поведение MCP под себя. Вывод простой: пощупать можно, особенно если болит время локальных билдов, но тащить в прод-процессы — аккуратно и с холодной головой. #L #AI #xcodebuild 👏

😄Почему мы стараемся минимизировать сторонние зависимости? Интеграция сторонней библиотеки часто кажется спасением: 10 минут
😄Почему мы стараемся минимизировать сторонние зависимости? Интеграция сторонней библиотеки часто кажется спасением: 10 минут вместо нескольких спринтов самостоятельной разработки. Но за этим стоят множественные скрытые риски. Разработчики часто идут на это из-за жёстких дедлайнов, сложности задачи или давления бизнеса и не всегда задумываются о долгосрочных последствиях 😖Основной недостаток на наш взгляд - это зависимость от maintainers библиотеки (vendor lock), из-за чего зачастую следуют: 🔺 Новые неожиданные баги с обновлениями версии Xcode или версии языка 🔺 Неопределенность с поддержкой - библиотеку запросто могут забросить и вы останетесь 1 на 1 с ней, формируя техдолг Помимо обозначенных рисков есть еще и другие неудобства: 🔺 Сложности с "выпиливанием" библиотеки (опыт Dodo с Realm) 🔺 Увеличение размера бинарника 🔺 Ожидания стабильного релиза после очередных "подарков" от Apple 🔺 Конфликты с другими зависимостями 🔺 Сложность отладки - не видно stack trace в исходниках библиотеки 🤔 С другой стороны, не всегда получается продать бизнесу идею разработки своего решения, особенно в быстрорастущих сегментах рынка и в условиях сильной конкуренции Нужен компромисс. В нашей практике необходимость сторонней зависимости оценивается на публичных техзащитах, в рамках которых разработчики анализируют новые фичи и пользовательские пути. Наши требования к самой библиотеке и ее интеграции, если будет доказана её важность, звучат так: 1️⃣ Необходимо владеть критическими частями кода, основной логикой, не отдавать флоу в "чужие руки" 2️⃣ Влияние зависимости на размер и скорость приложения должно быть контролируемым 3️⃣ Maintainers - надежные и проверенных сообществом, "живость" репозитория 4️⃣ Обращаем внимание на лицензию. Если зависимость критически важна и у нас недостаточно ресурса на разработку своего решения, то крайне желательно иметь возможность "форкнуть" и "причесать" под свои нужды в будущем в рамках техдолга 💎 Вместо итогов Мне понравилась цитата из свежей статьи на Medium: Если ты не контролируешь код, тогда код контролирует тебя Имхо, со сторонними зависимостями это справедливо вдвойне, тк даже не вы написали этот код и зачастую вы его даже не видите в отладке Думайте критически, подходите к проекту осознанно и не отпускайте все на автопилот 💫 #iOS #SoftwareArchitecture #Dependencies #TechDebt 👏

😄 Мифы о совершенной архитектуре Многие команды внедряют достаточно сложные архитектуры (VIPER, Clean Architecture), которые признаны неким стандартом, но которые не решают их реальных задач, при этом увеличивают объем кода, время сборки проекта и время погружения разработчиков. Но идеальная архитектура это та, которая соответствует размеру команды и сложности бизнес-процессов. Мистер Хотфикс проанализировал 147 iOS проектов и сделал для нас много интересных выводов. Что говорит статистика? - Распределение: MVVM (41%), MVC (34%), VIPER/Clean (18%), TCA (5%), another (2%). - Проблема: 73% проектов используют архитектуры, которые не решают их фактические проблемы. - Последствия чрезмерного проектирования: Внедрение Clean Architecture в средних командах часто ведет к росту объема кода на 143%, замедлению разработки на 67% и увеличению времени онбординга новых разработчиков до 3 недель. Какие архитектуры популярны? - MVC (Model-View-Controller): - Когда работает: Команды 1–3 человека, простые приложения. - Проблема: Massive View Controller возникает не из-за самой архитектуры, а из-за неумения выделять сервисы (у 89% проблемных приложений). - MVVM (Model-View-ViewModel): - Когда работает: Золотая середина для команд 3–10 человек, особенно в SwiftUI. - Плюсы: Повышает покрытие тестами до 67% (против 23% в MVC) при умеренном росте кодовой базы (+35%). - VIPER / Clean Architecture: - Когда работает: Команды 15+ человек, финансовые/медицинские приложения с ценой ошибки в миллионы. - Минусы: Экстремальный избыток кода (одна фича может занимать 7 файлов и 730 строк кода против 3 файлов и 260 строк кода в MVVM). - TCA (The Composable Architecture): - Когда работает: Команды уровня Senior, которым нужна 100% тестируемость и предсказуемое состояние. - Риски: Высокий порог входа (2–3 месяца обучения) и возможные проблемы с производительностью. Как выбрать свою архитектуру? - Стартап / MVP (1–3 devs): SwiftUI + простой MVVM. Приоритет на скорость. - Среднее приложение (4–8 devs): MVVM + Coordinator + Dependency Injection. - Enterprise (10+ devs): Clean Architecture или модульный MVVM. Приоритет на масштабируемость. - А лучше: проанализировать свои задачи и проблемы, и выбрать архитектуру, которая будет решать именно их. Какие выводы можно сделать? - Главный архитектурный антипаттерн: Использовать «энтерпрайз» решения для проблем стартапа. - Когда менять архитектуру: Только если текущая система «взорвется» в ближайшие 3 месяца. Если она продержится еще 2 года, рефакторинг не в приоритете. - Важнее архитектуры: Чистота кода, регулярное ревью и тесты. Важно помнить, что помимо парадигмальной смены архитектуры, есть много способов улучшить кодовую базу. Repository, Coordinator и DI можно внедрить независимо от выбора архитектуры. Да и сам выбор архитектуры не будет гарантировать успех потому, что хорошо приготовленный MVC лучше недожаренного Clean Architecture. 📎 The Architecture You’re Implementing Isn’t the Right One (And That’s Okay) #D #Arch #Holywar 👏

😏 SwiftUI: почему Group всё ещё считается вредным Почитал интересную статью от Two Cent Studios про контейнер Group в SUI –
😏 SwiftUI: почему Group всё ещё считается вредным Почитал интересную статью от Two Cent Studios про контейнер Group в SUI – и она очень точно формулирует проблему, с которой многие сталкивались, но не сразу могли понять. 🍕 Что вообще такое Group В SUI Group часто воспринимается как способ логически сгруппировать несколько View. Он не участвует в layout и не появляется в иерархии, а лишь влияет на то, как SUI обрабатывает вложенные элементы. И именно эта неочевидность часто становится источником проблем. 😫 Где начинаются проблемы
Group {
    if isLoading {
        ProgressView()
    } else {
        ContentView()
    }
}
.onAppear {
    fetchData()
}
Интуитивно кажется, что fetchData() вызовется один раз – при появлении Group. Но на практике SUI распространяет onAppear на каждое View внутри Group. В результате fetchData() может вызваться и для ProgressView, и для ContentView. То есть логика внезапно начинает жить в двух местах, хотя визуально это вообще не очевидно. 🍕 Главный посыл статьи Ключевая мысль статьи сводится к следующему: Group чаще всего используется там, где логически должен быть отдельный View. ⚠️ Почему Group так легко превращается в проблему - Group не изолирует логику - Group не изолирует модификаторы и автоматически применяет их ко всем вложенным View - скрывает реальную структуру экрана - усложняет понимание body, особенно при условиях Код выглядит компактно, но становится менее предсказуемым. ✅ Что использовать вместо Group 1. Вынос в отдельную View Вместо:
Group {
    Text("Title")
    Text("Subtitle")
}
.foregroundStyle(.red)
Лучше:
HeaderView()
    .foregroundStyle(.red)
- лучше читается - проще переиспользовать - легче тестировать 2. Реальные layout-контейнеры Если важно именно как элементы располагаются на экране, а не просто сгруппировать код – подойдут: - VStack - HStack - ZStack - Grid - Section Они явно показывают структуру интерфейса, а не маскируют её. 3. ViewBuilder Если Group появляется просто потому, что body стал слишком большим – это хороший сигнал к декомпозиции, а не к ещё одному уровню вложенности. 😅 В итоге Group не решает задачу структуры интерфейса. Он лишь влияет на то, как SUI обрабатывает вложенные View, не делая это очевидным из кода. В результате логика жизненного цикла и применение модификаторов становятся менее прозрачными. Практическое правило простое: если в коде появляется Group, стоит проверить, не напрашивается ли здесь отдельный View. #R #SwiftUI 👏

🤖 Все, что нужно знать о push-уведомлениях в iOS Иногда одна статья хорошо подсвечивает, насколько push-уведомления в iOS — это не «показать алерт», а сложная система с правилами, состояниями и ограничениями. Вот пример такого триггера для размышлений. За пушами скрывается гораздо больше: - Apple Developer Account, ключи APNs и сертификаты - Permissions и почему токен ≠ разрешение - Alert, Rich, Silent и VoIP пуши - Почему PushKit нужен для VoIP - Зачем VoIP push обязан приводить к CallKit - mutable-content и content-available - Extensions и их реальные ограничения - Как backend общается с APNs - Background, suspended state и лимиты фоновой работы Большая часть багов с пушами появляется не в коде UI, а на стыке этих слоёв и ожиданий от системы. Если будет интересно — могу разобрать весь lifecycle пуша целиком: от создания ключей в Apple Developer до пробуждения приложения в фоне и реальных ограничений iOS. #L #Push 👏

😋 Как работают xcodebuild, swift-build и Swift Build — разница и отношения внутри экосистемы Swift В продолжение рассмотренных тем касающихся систем сборки: 😃 Tuist снова завозит магию. 🤔 Компиляторы vs системы сборки. В Swift существует три разные сущности: swift-build - ядро системы сборки, реализованное в репозитории swift-build. • Он основан на llbuild и служит единым движком, который может планировать и исполнять сборочные задачи для разных фронтов; • Он не знает напрямую о форматах .xcodeproj или Package.swift. Вместо этого он оперирует промежуточным представлением проекта, называемым PIF (Project Intermediate Format) — абстрактный граф сборки; • Это то, что Xcode и SwiftPM используют под капотом для фактической сборки после того как манифесты/проекты интерпретированы и конвертированы в PIF. swift build - система-сборки для сборки Swift Package Manager. • cобирает только SwiftPM-пакеты (Package.swift); • парсит манифест, строит граф таргетов, генерирует PIF и передаёт его движку сборки; • вызывает движок сборки (в будущем это будет Swift Build вместе с опцией --build-system=swiftbuild). xcodebuild - система-сборки Xcode-проектов/воркспейсов. • читает .xcodeproj/.xcworkspace и Build Settings; • разрешает схемы, таргеты, зависимости; • конвертирует Xcode-конфигурацию в PIF; • затем передаёт PIF в swift-build для фактического исполнения.
То есть xcodebuild не вызывает swiftc напрямую через жесткие встроенные правила — он сначала интерпретирует проект, генерирует промежуточное представление и затем передаёт его в swift-build для сборки.
#L #xcodebuild #swiftbuild 👏

🤪 Swift Configuration 1.0 — появился стабильный, типобезопасный инструмент для работы с конфигурациями в Swift-проектах. Теперь можно единообразно собирать конфиг из ENV, файлов, аргументов командной строки и своих провайдеров, без самописных прослоек и разрозненной логики. Это особенно ценно для CLI-утилит и серверных приложений. Из ближних примеров: те же Tuist Env-ы вполне можно было бы реализовать на Swift Configuration нативнее, чем через кастомные решения.

let config = ConfigReader(providers: [
    EnvironmentVariablesProvider(),
    try await FileProvider<JSONSnapshot>(filePath: "config.json")
])

let apiURL = config.string(forKey: "api.url")
Инструмент упорядочивает источники, позволяет переопределять значения и расширяется собственными провайдерами. Отличный шаг для экосистемы Swift. #L #SwiftConfiguration #Env 👏

🤔 Вчера обсуждали с нашими хорошими друзьям и коллегами из Яндекса тему использования AI-кодеров и связанных с этим security-рисков (отсылка к их открытому рассказу на YouTube). Позиция у коллег довольно прагматичная: - Сам код без секретов коммерческой ценности почти не несет. Сегодня одна реализация, завтра другая. - Чувствительность модулей зависит от домена. В банке понятно, что есть особо критичные части. В обычном e-commerce секретов немного: корзина, витрина, каталог. - Всё заранее согласовано с безопасностью, получено официальное добро. - Контекст кодера должен быть ограничен. Не всё и не из всей монорепы нужно отдавать в облачный embedding. Подход абсолютно рабочий, но не универсальный. У проектов с другой спецификой бизнеса может быть куда более низкая толерантность к риску. И важно помнить несколько принципов опеки над своим кодом: - ограничивайте контекст AI-кодера - используйте .cursorignore/.claudeignore - держите только проверенные MCP и фильтруйте запросы от потенциальных prompt injection (мы писали про это тут). Почему вообще об этом стоит задумываться? Пример этого года хорошо иллюстрирует, что инструменты разработчика могут быть использованы и атакующими. В одном из кейсов злоумышленники применили Claude для автоматизации поиска уязвимостей и шантажа компаний. История светилась в NBC и других источниках и выглядит довольно серьезно. AI-кодеры дают огромный прирост скорости, но требуют осознанного контурa безопасности. Важно понимать, что безопасно в вашем домене, а что нет, и какое количество контекста вы готовы доверить облаку. #L #AI #Security 👏

🤪 Linux Foundation анонсировала Agentic AI Foundation - новый нейтральный фонд для развития открытых стандартов и инструментов для агентных AI-систем. В его стартовый пул вошли такие проекты, как Model Context Protocol (MCP) от Anthropic, AGENTS.md от OpenAI и фреймворк goose, а также поддержка крупных игроков (Google, Microsoft, AWS, Cloudflare и др.). Цель инициативы - создать общие протоколы и экосистему для совместимых, открытых AI-агентов, избежать несовместимых проприетарных инструментов и ускорить развитие агентных решений под контролем сообщества разработчиков. P.S.: На фоне анонса национальной программы - Genesis Mission (направленной на стратегическое ускорение национальных AI-исследований и инфраструктуры), такой шаг по открытым стандартам и сотрудничеству выглядит как "балансирующий шаг": развитие открытой, стандартизированной платформы может усилить экосистему и обеспечить более широкую совместимость инструментов, чем закрытые проприетарные подходы. #L #AI 👏

😋 Swift Bits: @objc vs dynamic Вчера мы говорили про compile и runtime. Сейчас - поговорим про интероп с objc в Swift, и зачем нужны @objc и dynamic. @objc Делает символ «видимым» для Objective-C runtime. Что даёт: • присваивает selector • для свойств getter и setter раскрываются в Objective-C методы: • регистрирует классы в ObjC runtime: objc_addClass • позволяет использовать swizzling, KVС/KVO • ObjC-код вызывает метод через message dispatch
Swift может игнорировать динамику и вызвать @objc-метод статически или через vtable.
@objc не заставляет Swift использовать objc_msgSend. dynamic - "is what forces Objective-C–style message dispatch even from Swift". #L #objc #runtime #swift #interop 👏