Если вы используете 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Openai
Security
How to securely operate and manage Codex agents
🔥3 1
В долгоживущих проектах часто возникают проблемы с инструментами и архитектурами. Они имеют свойство накапливаться и перемешиваться. Старый код где-то на 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Medium
Combine vs Async/Await: Choosing the Right Concurrency Model for Networking
Your iOS networking is stuck between two worlds. Learn when to use Combine’s reactive streams vs Async/Await’s structured concurrency —…
❤4 3🔥2
Поэтому буду по-тихоньку "доставать из загашника".
Автор в статье пытается сделать кэш.
Ну не столько кеш, сколько упрощённую модель мира, в которой механизмы доступные из коробки начинают работать.
Он берёт 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Jeffverkoeyen
10× faster Xcode CI builds with slot caching — featherless software design
❤4🔥2
Еще одна статья про сравнение инструментов распараллеливания работы. Каждый инструмент решает свою задачу (последовательные операции, реактивные потоки, и защита общего состояния соответственно), как их сочетать и какие типичные ошибки нужно избегать при проектировании реального 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Medium
Mastering Swift Concurrency: When to Use Async/Await vs Combine vs Actors
Navigate through Swift’s three concurrency models and create faster and more safe iOS applications that do not freeze your UI.
🔥4💯3
Не плохая статья про то, как на самом деле работают 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6💯3 3
Решил начать с темы несложной, но полезной.
Про 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
- тестовые файлы с общей структурой
Особенно полезно, когда:
- в проекте есть устоявшаяся архитектура
- важно соблюдать единый стиль
- в команду приходят новые разработчики
🍕 Почему полезно использовать шаблоны:
- меньше рутинных действий
- меньше ошибок от копипаста
- единая структура по проекту
- проще поддерживать кодовую базу
- быстрее старт новых фич
Но при регулярном использовании он заметно упрощает повседневную работу и помогает поддерживать аккуратную и предсказуемую структуру проекта.
#R #Xcode #Templates
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
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
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4💯3
На этот раз про
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
Please open Telegram to view this post
VIEW IN TELEGRAM
Листал свой фид, искал вдохновение о чем бы написать в канал и нашелся, на первый взгляд, идеальный кандидат на первый пост в этом году от меня
О чем: 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 ярдов - не понятно,
• не припомню, чтобы по статистике от 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 анимациями именно из-за сборщика мусора, напишите в комменты
По итогу ощущение такое... то-ли кликбейт, то-ли нейронка написала (длинных "—" много, да, это косвенно), грустно
А вот выводы автор делает как будто в отрыве от всей остальной статьи, они довольно универсальные
👉 Кооперируйтесь с компилятором - переложите на него больше работы, уменьшив число проверок в runtime
👉 Подходите к коду осознанно
👉 Код должен быть максимально явным, не допускайте двусмысленности
👉 Используйте систему типов для описания бизнес логики (отсылка на Domain Driven Design - там это важная часть)
и от себя
⚡️Думайте критически, в эпоху нейронок важно фильтровать
#M #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
Medium
Swift Wasn’t Created to Replace Objective-C. It Was Created to Replace You.
The uncomfortable truth about why Apple spent 4 years building a language in secret — and what it means for your career
🔥5 3💩2
Модульность это разделение кодовой базы на четко очерченные, изолированные единицы с явными границами ответственности.
Каждый модуль имеет публичный интерфейс, скрывает внутреннюю реализацию и может эволюционировать независимо.
Модульность нужна не всегда. Для небольших проектов и прототипов она часто создает лишние накладные расходы. В этом случае простота и скорость может быть важнее архитектурной чистоты.
Но когда продукт стабилизируется и становится ясно, что кодовая база будет расти, модульность помогает управлять сложностью, задает границы владения кодом и предотвращает деградацию в тесно связанный монолит.
Проектирование структуры до написания кода
Архитектуру стоит продумывать до начала реализации, а не по ходу роста проекта.
Простая диаграмма модулей помогает определить границы, проясняет зависимости, снижает количество реактивных решений позже.
Начинать рекомендуется с базового слоя: общие модели данных, сетевой слой, фундаментальные сущности. Раннее формирование этого слоя снижает риск болезненных переделок в будущем.
Три основные категории модулей
🛠️ Foundation-модули содержат общие модели, примитивы, инфраструктурные компоненты. Они не зависят ни от чего выше по иерархии и используются практически везде. Также они не должны содержать пользовательские сценарии.
🧰 Service-модули содержат переиспользуемую логику и сервисы. Они зависят от Foundation и используются фичами. Foundation-модули никогда не должны зависеть от Service-модулей, это нарушает иерархию.
🚚 Feature-модули содержат пользовательские сценарии (онбординг, оплата, профиль и т. д.). Они могут зависеть от Foundation и Services, но не должны зависеть друг от друга. Горизонтальные связи между фичами быстро разрушают архитектуру и возвращают монолитные проблемы.
Модульность ради модульности
Внедрение модульности как модного веяния без должного проектирования ведет к проблемам при которых возникают циклы зависимостей, универсальные сервисы, раздутые публичные API. В долгосрочной перспективе растет технический долг, а кодовую базу становится поддерживать труднее чем монолит.
Хотя определенные плюсы все равно будут присутствовать. Будет меньше конфликтов на мержах и ускорится параллельная разработка.
📎 Modularity as an Architectural Choice
#D #Arch #Modularity #Clean
Please open Telegram to view this post
VIEW IN TELEGRAM
Livsy Code → Learn Swift the smart way
Modularity as an Architectural Choice → Livsy Code
Greetings, traveler! Modularity is an architectural approach where a codebase is split into well-defined, independent units with explicit responsibilities and boundaries. Each module exposes a clear public interface and hides its internal details, allowing…
🔥4 4❤2
У каждого модуля должен быть явно определен контракт:
🛠️ В Foundation-модулях допустим широкий API, но изменения будут дороже.
🧰 В Service-модулях API должен быть узким и сфокусированным, его рост является сигнал о "божественной" ответственности.
🚚 В Feature-модулях должен быть минимальный интерфейс: точка входа и результат выполнения сценария.
Навигация и взаимодействие между фичами
Внутренняя навигация это ответственность самой фичи. Переходы между фичами не должны происходить напрямую. Часто они выносятся во внешний координатор (AppCoordinator, TabCoordinator и т. д.).
Фича сигнализирует о завершении сценария, а координатор решает куда идти дальше и передает данные следующей фиче. Это сохраняет изоляцию и прозрачность зависимостей.
Сборка фич и обмен данными
Координатор не должен собирать внутренности фичи. Каждая фича сама знает, какие зависимости ей нужны и предоставляет assembly API (factory, builder и т.п). Обмен данными происходит через result-модели, а при наличии общих моделей, они выносятся в отдельный нейтральный модуль.
Для сложного взаимодействия возможен mediator-модуль, который знает о нескольких фичах, управляет их взаимодействием. Такой подход используется реже из-за архитектурной сложности.
Протокольные bridge-модули
Bridge-модули на протоколах выглядят красиво с точки зрения чистой архитектуры, но увеличивают количество модулей, время сборки и когнитивную нагрузку. Часто они создают иллюзию слабой связанности.
Они оправданы в конкретных случаях где требуется изоляция тяжелых зависимостей, тестирование или постепенный переход от монолита. Внутри фич протоколы допустимы, но стоит иметь во внимании, что гипергибкость почти никогда не окупается.
Какие выводы можно сделать?
Модульность это не слепой рефакторинг, а осознанная архитектурная практика, которая снижает сложность, улучшает масштабируемость команды, повышает предсказуемость разработки, а также позволяет превращать код в долгосрочные активы.
Инструменты могут помочь, но не заменяют архитектурное мышление, дисциплину и понимание границ ответственности. Без этого модульная система быстро скатывается в более замаскированный хаос.
📎 Modularity as an Architectural Choice
#D #Arch #Modularity #Clean
Please open Telegram to view this post
VIEW IN TELEGRAM
Livsy Code → Learn Swift the smart way
Modularity as an Architectural Choice → Livsy Code
Greetings, traveler! Modularity is an architectural approach where a codebase is split into well-defined, independent units with explicit responsibilities and boundaries. Each module exposes a clear public interface and hides its internal details, allowing…
❤3🔥2 2
В 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
——————
В разработке нередко встречаются ситуации, когда разные части проекта имеют различный внешний вид и поведение, что затрудняет поддержку, ведет к увеличению сроков выпуска обновлений и ухудшению качества продукта.
Решением подобных проблем является дизайн‑система, которая обеспечивает единую библиотеку компонентов и строгие правила их использования, позволяя сократить время разработки, минимизировать расхождения между частями продукта и значительно облегчить дальнейшую работу над проектом.
Наш братик и по совместительству Android‑разработчик из СЗ, в статье рассказывает, как строили мобильную дизайн‑систему на iOS и Android проекте на SUI и Compose, соответственно, и оптимизировали интерфейсы
#L #DesignSystem #iOS #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Особенности построения и развития дизайн-системы в мобильном приложении СберЗдоровья
При разработке ИТ‑продуктов команды нередко сталкиваются с ситуацией, когда разные части проекта имеют различный внешний вид и поведение, что затрудняет поддержку, ведет...
🔥4 4❤2
Существует 3 типа линковки:
• Static
• Dynamic
• Mergeable
Почему это важно? Тип линковки напрямую влияет на:
• модульность и управляемость архитектуры,
• размер приложения,
• скорость запуска.
Хороший разбор с примерами — тут.
Отдельно отмечу mergeable libraries. Tuist прямо говорит о cost of convenience,
и я с этим полностью согласен:
➡️ mergeable почти всегда сложнее организовать,
➡️ сложнее явно контролировать и дебажить, чем осознанная и прозрачная логика линковки.
Подход который использую я, и который сквозь время доказал свою пригодность и масштабируемость (под бинарные кеши всякие т.д. не страдая качеством):
• staticForDeploy — все библиотеки статические, кроме тех, что шарятся с экстеншонами
• dynamicForDev — всё динамика для комфортной разработки
Вся логика механизма зашита в Tuist.ProjectDenoscriptionHelpers, дополняется оверрайдами в CocoaPods и SPM.
Итог: быстрее старт приложения в проде, удобство разработки и контролируемая архитектура без магии.
P.S.: Если интересно, чуть больше года назад рассказывал об этом подробнее.
#L #Linkage #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
Livsy Code → Learn Swift the smart way
Static, Dynamic, and Mergeable Linking in Modular iOS Apps → Livsy Code
Greetings, traveler! Modularization changes how a project feels day to day. The codebase becomes easier to reason about, feature work becomes more parallel, and dependency boundaries start to matter. At the same time, the build system becomes part of the…
🔥6
Если коротко, то тут статья, а тут макрос, который сгенерирует 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: Включает проверки в рантайме для обнаружения ошибок, если мы возобновляли continuations более одного раза или совсем не возобновляли их.
UnsafeContinuation: Выключает проверки безопасности для лучшей производительности.
Плюсы:
Минусы?
📎 Modern Concurrency and Legacy code
#D #Arch #Legacy #Macros
Please open Telegram to view this post
VIEW IN TELEGRAM
SwiftDifferently
Modern Concurrency and Legacy code
‘We can’t touch that code — it’s all callback-based!’ Sound familiar? As a developer, you’ve probably heard this countless times, or even said it yourself.
🔥3
Если вы уже используете 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Reddit
From the SideProject community on Reddit
Explore this post and more from the SideProject community
🔥4
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•
@EnvironmentObjectObservation не заменяет их, а дополняет.
ObservableObject это часто более удобный и читаемый вариант.#R #SwiftUI #Observation
Please open Telegram to view this post
VIEW IN TELEGRAM
Tanaschita
Migrating to the Observation framework in SwiftUI
Learn how to use SwiftUI's @Observable macro and how to migrate existing ObservableObject, @StateObject, and @ObservedObject-based code to the Observation framework in Swift.
+ Tuist превращает все это дело в skill 🛠️
📦 Миграция Mastodon iOS
🎮 Первый skill — migrate
#L #Tuist #AI
Please open Telegram to view this post
VIEW IN TELEGRAM
Хочется сделать серию постов по основам 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-сценарии
- публичные API
- системы, где важны кэширование, простота и масштабируемость
Почему: REST максимально использует возможности HTTP: методы, статусы, cache-control.
Он прост, прозрачен и отлично поддерживается инструментами.
📍 REST — дефолтный выбор, если нет веской причины делать иначе.
🔹 GraphQL
Что это: Язык запросов и runtime, где клиент сам описывает, какие данные ему нужны.
Транспорт:
- чаще всего HTTP
- иногда WebSocket (но это уже про real-time)
Когда применять:
- сложные графы данных
- разные клиенты с разными требованиями к payload
- желание сократить количество запросов
Почему: GraphQL снимает проблему overfetching/underfetching, но усложняет сервер и наблюдаемость.
📍 GraphQL — про гибкость клиента, а не про простоту системы.
🔹 RPC (gRPC, Thrift, JSON-RPC)
Что это: Удалённый вызов процедур: клиент вызывает метод, сервер его исполняет.
Транспорт: не привязан к HTTP
- gRPC — HTTP
- Thrift — TCP / HTTP / custom transport
Когда применять:
- межсервисное взаимодействие
- высокая производительность
- чёткие контракты и кодогенерация
Почему: RPC ближе к обычному программированию: вызвал метод — получил результат. Это эффективно, но хуже ложится на публичные API и браузный мир.
📍 RPC — лучший выбор для внутренних систем и платформенных API.
#L #Network #HTTP #TCP #REST #SOAP #GraphQL #RPC
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5 4 2
В Claude Code появилась экспериментальная фича Agent Team.
Что позволяет запускать виртуальную команду ИИ-сессий, которые работают параллельно над одной задачей, берут задачи из общего пула и могут общаться между собой напрямую.
- можно распараллеливать работу по пуллу задач,
- тимейты говорят друг с другом и сами решают, что делать дальше,
- и могут критиковать друг друга,
- полезно для сложных фич, исследований и коворкинга с ИИ.
Но:
💸 дорого — каждый агент работает как отдельная сессия и "жжёт" токены,
🧪 экспериментально — фича отключена по умолчанию, поэтому, наверное, пока стоит осторожно.
#L #AI #Agent #Team
Please open Telegram to view this post
VIEW IN TELEGRAM
Claude Code Docs
Orchestrate teams of Claude Code sessions - Claude Code Docs
Coordinate multiple Claude Code instances working together as a team, with shared tasks, inter-agent messaging, and centralized management.