YDC — Pizza Powered iOS – Telegram
YDC — Pizza Powered iOS
242 subscribers
65 photos
95 links
Young Da Code 👨‍💻
Первый командный дайджест о мобильной разработке 🍕
Download Telegram
🤪 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
33
🤔 Вчера обсуждали с нашими хорошими друзьям и коллегами из Яндекса тему использования AI-кодеров и связанных с этим security-рисков (отсылка к их открытому рассказу на YouTube).

Позиция у коллег довольно прагматичная:
- Сам код без секретов коммерческой ценности почти не несет. Сегодня одна реализация, завтра другая.
- Чувствительность модулей зависит от домена. В банке понятно, что есть особо критичные части. В обычном e-commerce секретов немного: корзина, витрина, каталог.
- Всё заранее согласовано с безопасностью, получено официальное добро.
- Контекст кодера должен быть ограничен. Не всё и не из всей монорепы нужно отдавать в облачный embedding.

Подход абсолютно рабочий, но не универсальный. У проектов с другой спецификой бизнеса может быть куда более низкая толерантность к риску.
И важно помнить несколько принципов опеки над своим кодом:
- ограничивайте контекст AI-кодера
- используйте .cursorignore/.claudeignore
- держите только проверенные MCP и фильтруйте запросы от потенциальных prompt injection (мы писали про это тут).

Почему вообще об этом стоит задумываться? Пример этого года хорошо иллюстрирует, что инструменты разработчика могут быть использованы и атакующими. В одном из кейсов злоумышленники применили Claude для автоматизации поиска уязвимостей и шантажа компаний. История светилась в NBC и других источниках и выглядит довольно серьезно.

AI-кодеры дают огромный прирост скорости, но требуют осознанного контурa безопасности. Важно понимать, что безопасно в вашем домене, а что нет, и какое количество контекста вы готовы доверить облаку.

#L #AI #Security

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥52
🤪 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42
😋 Как работают 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🤖 Все, что нужно знать о 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥93
😏 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("Subnoscript")
}
.foregroundStyle(.red)


Лучше:
HeaderView()
.foregroundStyle(.red)


- лучше читается
- проще переиспользовать
- легче тестировать

2. Реальные layout-контейнеры
Если важно именно как элементы располагаются на экране, а не просто сгруппировать код – подойдут:
- VStack
- HStack
- ZStack
- Grid
- Section

Они явно показывают структуру интерфейса, а не маскируют её.

3. ViewBuilder
Если Group появляется просто потому, что body стал слишком большим – это хороший сигнал к декомпозиции, а не к ещё одному уровню вложенности.

😅 В итоге
Group не решает задачу структуры интерфейса.
Он лишь влияет на то, как SUI обрабатывает вложенные View, не делая это очевидным из кода.

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

Практическое правило простое:
если в коде появляется Group, стоит проверить, не напрашивается ли здесь отдельный View.

#R #SwiftUI

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
💯53🔥2
😄 Мифы о совершенной архитектуре

Многие команды внедряют достаточно сложные архитектуры (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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7💯2
😄Почему мы стараемся минимизировать сторонние зависимости?

Интеграция сторонней библиотеки часто кажется спасением: 10 минут вместо нескольких спринтов самостоятельной разработки. Но за этим стоят множественные скрытые риски. Разработчики часто идут на это из-за жёстких дедлайнов, сложности задачи или давления бизнеса и не всегда задумываются о долгосрочных последствиях

😖Основной недостаток на наш взгляд - это зависимость от maintainers библиотеки (vendor lock), из-за чего зачастую следуют:

🔺 Новые неожиданные баги с обновлениями версии Xcode или версии языка
🔺 Неопределенность с поддержкой - библиотеку запросто могут забросить и вы останетесь 1 на 1 с ней, формируя техдолг

Помимо обозначенных рисков есть еще и другие неудобства:

🔺 Сложности с "выпиливанием" библиотеки (опыт Dodo с Realm)
🔺 Увеличение размера бинарника
🔺 Ожидания стабильного релиза после очередных "подарков" от Apple
🔺 Конфликты с другими зависимостями
🔺 Сложность отладки - не видно stack trace в исходниках библиотеки

🤔 С другой стороны, не всегда получается продать бизнесу идею разработки своего решения, особенно в быстрорастущих сегментах рынка и в условиях сильной конкуренции

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

1️⃣ Необходимо владеть критическими частями кода, основной логикой, не отдавать флоу в "чужие руки"
2️⃣ Влияние зависимости на размер и скорость приложения должно быть контролируемым
3️⃣ Maintainers - надежные и проверенных сообществом, "живость" репозитория
4️⃣ Обращаем внимание на лицензию. Если зависимость критически важна и у нас недостаточно ресурса на разработку своего решения, то крайне желательно иметь возможность "форкнуть" и "причесать" под свои нужды в будущем в рамках техдолга

💎 Вместо итогов

Мне понравилась цитата из свежей статьи на Medium:

Если ты не контролируешь код, тогда код контролирует тебя

Имхо, со сторонними зависимостями это справедливо вдвойне, тк даже не вы написали этот код и зачастую вы его даже не видите в отладке

Думайте критически, подходите к проекту осознанно и не отпускайте все на автопилот 💫

#iOS #SoftwareArchitecture #Dependencies #TechDebt

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥532
😒 Claude Code + XcodeBuildMCP + xcodemake.
Попытка сделать быстрые инкрементальные билды для AI, рядом с xcodebuild.

Как это работает:
xcodemake сначала прогоняет обычный xcodebuild, анализирует его и генерирует Makefile.
Дальше при повторных сборках компилируется только изменённый код (без ресурсов и ассетов).
За счёт этого повторные билды могут быть заметно быстрее.

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

Сам XcodeBuildMCP — это MCP-сервер, который даёт AI доступ к Xcode: сборки, схемы, симуляторы, девайсы, discovery-проекта и т.д.
Есть конфигурация: можно включать/выключать инкрементальные билды, ограничивать доступные workflow, настраивать поведение MCP под себя.

Вывод простой: пощупать можно, особенно если болит время локальных билдов, но тащить в прод-процессы — аккуратно и с холодной головой.

#L #AI #xcodebuild

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
22
😄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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥321
😏 Использование семантического версионирования (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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
433
🍕 Хочется потихоньку выходить из новогоднего вайба и начинать набирать тонус и жизненный и рабочий.
И начать год хочется с первой статьи — и снова про 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
54
😋 Безопасность 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥31
😄 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
43🔥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
4🔥2
😄 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4💯3
🤖 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6💯33
😅 Вслед за остальными черепашками медленно вылезаю из панциря после новогодних праздников.
Решил начать с темы несложной, но полезной.

Про 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

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🦾 Наткнулся на пост про 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

👏
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
7
😄Рубрика кликбейт или "потраченного времени жаль"

Листал свой фид, искал вдохновение о чем бы написать в канал и нашелся, на первый взгляд, идеальный кандидат на первый пост в этом году от меня

О чем: 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 анимациями именно из-за сборщика мусора, напишите в комменты 🍿

По итогу ощущение такое... то-ли кликбейт, то-ли нейронка написала (длинных "—" много, да, это косвенно), грустно 😭

🍕А выводы то какие?

А вот выводы автор делает как будто в отрыве от всей остальной статьи, они довольно универсальные

👉 Кооперируйтесь с компилятором - переложите на него больше работы, уменьшив число проверок в runtime
👉 Подходите к коду осознанно
👉 Код должен быть максимально явным, не допускайте двусмысленности
👉 Используйте систему типов для описания бизнес логики (отсылка на Domain Driven Design - там это важная часть)

и от себя

⚡️Думайте критически, в эпоху нейронок важно фильтровать базар контент

👏

#M #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥53💩2