🇷🇺 В России «отрубают» FaceTime. По данным Роскомнадзор, сервис «используется для организации терактов и мошенничества» (как и многие другие мессенджеры и VPN).
🛑 Вместе с этим продолжают совершенствовать ограничения к VPN.
🤔 Кто уже начал использовать Max?
#L #sanctions #FaceTime #VPN
👏
🛑 Вместе с этим продолжают совершенствовать ограничения к VPN.
#L #sanctions #FaceTime #VPN
Please open Telegram to view this post
VIEW IN TELEGRAM
Reuters
Russia blocks Apple's FaceTime in mounting push against foreign tech platforms
Russia has blocked Apple's video-calling app FaceTime, the state communications watchdog said on Thursday, as part of an accelerating clampdown on foreign tech platforms that authorities allege are being used for criminal activity.
Это давало магическое ощущение:
типобезопасно, без строковых SQL-запросов, удобно фильтровать и получать данные.
Чтобы понять всю механику работы, я тогда потратил не один день на чтение документации и мучения ведущего разраба, но кайф от подхода был огромный.
Позже я пытался воспроизвести то же на Symfony + PHP, и почувствовал огромную разницу работы:
другие абстракции, ActiveRecord по всему проекту…
В итоге (менее типизированный) почти-голый SQL на PHP, как ни странно, работал кратно быстрее, чем ASP.NET со спецификациями.
На то было много причин, от местоположения арендованных серверов, до специфики работы паттернов и фильтрации, сейчас не об этом.
Когда я пришёл в мобилку, первый проект тоже был с БД, и я долго объяснял тимлиду, почему типобезопасный доступ к данным - топ.
На самом деле я просто хотел того же опыта, той же предсказуемости.
И вот теперь — появился #Predicate, который по сути является макросом над NSPredicate.
То есть всё те же плюсы типобезопасности + читабельности, но без существенного падения перформанса, по идее (посмотрим на практике).
В целом, макросы всё глубже прорастают в Swift-разработку — и, имхо, делают нашу жизнь сильно лучше.
#L #SwiftData #Predicate
Please open Telegram to view this post
VIEW IN TELEGRAM
Medium
A #Predicate Secret in Swift: Why One Line Changes Everything?
The surprising answer behind invisible errors in your SwiftData queries
🔥4❤2 2
🔄 SwiftUI: удобная прокрутка с помощью ScrollTargetBehavior
Почитал хорошую статью на Medium про механизм прокрутки в SwiftUI – ScrollTargetBehavior.
Решил поделиться самой полезной выжимкой + реальными примерами.
🧲 Что вообще такое “snap”?
Snap-прокрутка – это когда после скролла список «прилипает» к ближайшему элементу.
Не останавливается где попало, не обрезает карточку наполовину, а аккуратно доезжает до нужной позиции.
Примеры из жизни:
- карусель App Store
- галереи фото
- карточки в музыкальных приложениях
Раньше приходилось собирать на UIScrollViewDelegate, offset-вычислениях и тд.
Теперь – один модификатор.
🍕 Что даёт ScrollTargetBehavior
В SwiftUI есть два поведения «из коробки»:
-
Постраничная прокрутка. Один свайп = один экран/элемент.
-
Выравнивание по ближайшему элементу – подходит для карточек и горизонтальных списков.
И самое интересное: можно написать своё собственное поведение.
Учитывать скорость свайпа, размеры элементов, направление – и решать, куда именно «приклеится» список.
👩💻 Примеры
1. Карусель изображений с paging
Теперь листается как полноценная галерея – экран за экраном.
2. Вертикальный список, который «прилипает» к ближайшей карточке
После прокрутки список автоматически выравнивается по ближайшему элементу.
3. Кастомный snap: быстрый свайп пролистываем на 2 карточки
Использование:
🍕 Почему это лучше старых решений
До iOS 17 snap-прокрутку собирали через:
- вычисление scrollOffset
- DragGesture + кастомные вычисления позиции
- UIScrollViewDelegate через UIViewRepresentable
Теперь:
- поведение описано декларативно
- ScrollView сам учитывает инерцию и скорость жеста
- одинаково работает в LazyVStack / LazyHStack / обычном ScrollView
- можно расширять собственными правилами
🎯 Что получаем?
ScrollTargetBehavior – современный, нативный и гибкий способ управлять прокруткой в SwiftUI:
- аккуратный snap
- предсказуемое и понятное поведение
- возможность тонкой настройки
- минимум костылей, максимум стабильности
#R #SwiftUI
👏
Почитал хорошую статью на Medium про механизм прокрутки в SwiftUI – ScrollTargetBehavior.
Решил поделиться самой полезной выжимкой + реальными примерами.
🧲 Что вообще такое “snap”?
Snap-прокрутка – это когда после скролла список «прилипает» к ближайшему элементу.
Не останавливается где попало, не обрезает карточку наполовину, а аккуратно доезжает до нужной позиции.
Примеры из жизни:
- карусель App Store
- галереи фото
- карточки в музыкальных приложениях
Раньше приходилось собирать на UIScrollViewDelegate, offset-вычислениях и тд.
Теперь – один модификатор.
В SwiftUI есть два поведения «из коробки»:
-
.pagingПостраничная прокрутка. Один свайп = один экран/элемент.
-
.viewAlignedВыравнивание по ближайшему элементу – подходит для карточек и горизонтальных списков.
И самое интересное: можно написать своё собственное поведение.
Учитывать скорость свайпа, размеры элементов, направление – и решать, куда именно «приклеится» список.
1. Карусель изображений с paging
ScrollView(.horizontal) {
LazyHStack(spacing: 0) {
ForEach(items) { item in
CardView(item)
.frame(width: UIScreen.main.bounds.width)
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.paging)
.scrollIndicators(.hidden)Теперь листается как полноценная галерея – экран за экраном.
2. Вертикальный список, который «прилипает» к ближайшей карточке
ScrollView {
LazyVStack(spacing: 16) {
ForEach(cards) { card in
CardView(card)
.containerRelativeFrame(.vertical)
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)После прокрутки список автоматически выравнивается по ближайшему элементу.
3. Кастомный snap: быстрый свайп пролистываем на 2 карточки
struct FastPaging: ScrollTargetBehavior {
func updateTarget(_ target: inout ScrollTarget,
context: ScrollTargetBehaviorContext) {
// если жест быстрый — пролистываем дальше
if context.velocity.magnitude > 1500 {
target.index += context.velocity.width > 0 ? 2 : -2
} else {
// стандартная логика
target = context.target
}
}
}Использование:
.scrollTargetBehavior(FastPaging())
До iOS 17 snap-прокрутку собирали через:
- вычисление scrollOffset
- DragGesture + кастомные вычисления позиции
- UIScrollViewDelegate через UIViewRepresentable
Теперь:
- поведение описано декларативно
- ScrollView сам учитывает инерцию и скорость жеста
- одинаково работает в LazyVStack / LazyHStack / обычном ScrollView
- можно расширять собственными правилами
🎯 Что получаем?
ScrollTargetBehavior – современный, нативный и гибкий способ управлять прокруткой в SwiftUI:
- аккуратный snap
- предсказуемое и понятное поведение
- возможность тонкой настройки
- минимум костылей, максимум стабильности
#R #SwiftUI
Please open Telegram to view this post
VIEW IN TELEGRAM
Автор декомпилирует Snowboard Kids 2 в режиме matching decompilation - когда итоговый C-код после компиляции должен давать тот же бинарь, что и оригинальный ассемблер.
🧠 Для работы он построил флоу с Claude-агентом:
1. Использует decomp.me для исходной декомпиляции.
2. Сравнивает результат компиляции восстановленного кода с оригинальным бинарём.
3. Если совпадение неполное - подключает агентов, которые ищут расхождения и итеративно повторяют цикл декомпиляция → компиляция → сравнение.
4. В случае стагнации или деградации агент передаёт задачу человеку.
✅ Где агенты хороши:
— ловят повторяющиеся паттерны в машинном коде;
— предлагают варианты функций, которые вручную копать долго;
— ускоряют черновые этапы и снимают рутину.
❌ Где они проваливаются:
— иногда ошибаются в базовой арифметике;
— «забывают» окружение (вплоть до выбранного компилятора);
— ломают control flow в ветвистых кусках в духе goto.
🔧 Вывод: как инструмент — 🔥.
Агенты реально ускоряют реверс и снимают тонны ручной боли.
Но полностью полагаться на ИИ нельзя: без человека это всё ещё красивая, но бесполезная поделка.
#L #AI #ReverseEngineering #Decompilation
Please open Telegram to view this post
VIEW IN TELEGRAM
Chris' Blog
Using Coding Agents to Decompile Nintendo 64 Games
A look at where coding agents help (or don’t) in the matching decompilation of Snowboard Kids 2 on the Nintendo 64.
❤3 3
Навеяло мысли после одно рабочего кейса.
Из-за недопонимания, ребята сделали ненужную работу.
И потом еще потратили время на откатывание, которое, к слову, можно было не делать.
Если бы верно обсудили варианты решений.
Мои правила, комммуникации в чатах:
1️⃣ Пиши всё в одном сообщении.
Приветствие, контекст, что нужно, сроки — одним четким блоком. Это экономит время и снижает шанс быть неправильно понятым.
2️⃣ Собирай обратную связь.
Уточняй, верно ли тебя поняли. Сам реагируй тоже одним сообщением и — если возможно — в треде. Подзывай всех участников, чтобы никто не выпал.
3️⃣ Фиксируй решение.
Одним финальным сообщением: контекст → решение → почему так. Это сильно снижает количество “а что в итоге решили?”.
💡 Самое важное — пункты 1 и 3.
И да, имхо, зачастую, “правильная коммуникация” — это 50–80% успеха задачи.
Наблюдение: люди с хорошими коммуникативными навыками растут в карьере быстрее. 😉
P.S.: Почитать о коммуникации от коучей можно много всего, базово, эти 3 правила работают со мной с начала карьеры, после того как один мой руководитель, обьяснил их мне при очередной моей попытке достать его "до кишок" своими вопросами по задаче.
#L #Communication
Please open Telegram to view this post
VIEW IN TELEGRAM
vc.ru
Рабочая коммуникация в мессенджерах. Как соблюсти границы свои и чужие? Как сделать так, чтобы вас поняли?
А в каком количестве чатов состоите вы? Рабочие, родительские, дружеские, семейные…оповещения из них приходят иногда каждую минуту. И на многое нужно реагировать, отвечать.
❤6
Мы часто пишем код так, будто машинка за кадром просто «выполняет инструкции», но в реальности путь от исходника до выполнения куда длиннее и интереснее.
Сегодня попробуем пройти его последовательно: от compile time и LLVM IR до Swift runtime, Obj-C runtime и механизмов диспетчеризации методов.
🧩 Compile Time vs Runtime:
Swift — язык, который сознательно переносит максимум работы на этап компиляции.
Чем больше информации компилятор узнает о типах, generics, наследовании, тем меньше остаётся неопределённости в рантайме, и тем быстрее будет работать ваш код.
Compile Time — что делает компилятор Swift:
- проверяет типы и связи между ними
- анализирует возможности оптимизации
- генерирует LLVM IR — промежуточное представление программы
- формирует метаданные типов и служебные таблицы, необходимые рантайму
решает, можно ли:
- специализировать generics в конкретный код
- де-виртуализировать вызовы
- развернуть протокол в статический вызов
- Если типы известны заранее — компилятор построит прямой статический вызов без участия runtime.
Runtime — что происходит «вживую»:
- выделяется память под объекты
- работает ARC
- инициализируются метаданные типов
- происходит lookup таблиц: vtable, witness table
- выполняется упаковка/распаковка типов в existential container
- работает Obj-C runtime
- вызываются методы — статические, виртуальные или динамические
Compile time строит все дороги и развязки. Runtime по ним едет.
🟣 Obj-C Runtime — всё объект, всё сообщение:
Чтобы оценить, насколько иначе работает Swift, сначала вспомним принцип Obj-C.
Объект в Obj-C — это структура, в которой есть поле isa:
struct objc_object {
Class isa;
};
Классы в objc одновременно и классы и обьекты.
Вызов метода в objc:
[obj doSomething];
на самом деле является:
вызовом функции
objc_msgSend(obj, @selector(doSomething))
, которая:
- читает obj->isa
- ищет селектор в кеше
- поднимается по иерархии классов (если не находит метод — запускает цепочку message forwarding)
- и только после всех попыток бросает unrecognized selector
Да, Objective-C — это надстройка над языком C, которая добавляет к нему объектно-ориентированную парадигму (ООП) и динамические возможности через систему сообщений и объекты, сохраняя при этом полную совместимость с кодом на чистом C, что позволяет использовать их совместно
🔵 Swift Runtime — другой мир:
Swift не опирается на Obj-C runtime (кроме совместимого кода) и имеет собственную модель исполнения.
Swift-структуры и enum:
- xранятся inline (на стеке или внутри других структур)
- не имеют isa
- становятся heap-объектами только при боксинге
Swift-классы:
- всегда heap-объекты
- имеют header, содержащий указатель на Swift type metadata
- если совместимы с Obj-C — получают и поле isa
То есть:
У value types нет Obj-C-объектности. У reference types есть типовая информация, но она не идентична Obj-C-isa — Swift организует её иначе.
🧬 LLVM IR — слой, где принимаются ключевые решения:
Swift не компилируется напрямую в машинный код — сначала он становится LLVM IR.
Это низкоуровневое, но типобезопасное представление, в котором компилятор:
- специализует generics (когда возможно)
- удаляет виртуальность
- inline-ит функции
- оптимизирует вызовы протоколов
- устраняет лишние копирования
- уменьшает динамику
⚙️ Именно на IR-уровне решается, каким будет вызов метода:
Static dispatch
- метод у struct/enum/extension
- метод final
- функция свободная
- generics-функция после специализации
Witness dispatch
Вызов через протокол, когда тип известен, но вызов идёт «через протокол».
Компилятор кладёт указатели методов в witness table, и вызов выполняется через неё.
Virtual dispatch
Если метод может быть переопределён — он попадает в таблицу виртуальных методов.
Если нельзя — становится статическим вызовом.
Dynamic Dispatch (Obj-C) Когда Swift-код:
- наследует NSObject
- помечен @objc
- помечен dynamic
Вызов идёт через objc_msgSend.
📎 Swift Runtime
#L #SwiftRuntime #MetodDispatch
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4💩2 2
Вчера мы говорили про 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Substack
Swift Bits: @dynamic vs @objc
Animate State change
❤4 2
- новый нейтральный фонд для развития открытых стандартов и инструментов для агентных 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
The White House
Launching the Genesis Mission
By the authority vested in me as President by the Constitution and the laws of the United States of America, it is hereby ordered: Section 1. Purpose.
❤3 3
Позиция у коллег довольно прагматичная:
- Сам код без секретов коммерческой ценности почти не несет. Сегодня одна реализация, завтра другая.
- Чувствительность модулей зависит от домена. В банке понятно, что есть особо критичные части. В обычном 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
Telegram
iOS Makes Me Hate
Использование AI-тулкитов в кровавом бигтехе
Обещал вам давно максимально практичный выпуск про ваши там Cursor'ы, Claude Code и тп и тд. Долго к нему шли. Но здесь уникальность в том, что показываем РЕАЛЬНУЮ КОДОВУЮ БАЗУ ПРОЕКТА.
Позвал своего коллегу…
Обещал вам давно максимально практичный выпуск про ваши там Cursor'ы, Claude Code и тп и тд. Долго к нему шли. Но здесь уникальность в том, что показываем РЕАЛЬНУЮ КОДОВУЮ БАЗУ ПРОЕКТА.
Позвал своего коллегу…
❤6🔥5 2
Теперь можно единообразно собирать конфиг из 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
Swift.org
Swift Configuration 1.0 released
Every application has configuration: in environment variables, configuration files, values from remote services, command-line flags, or repositories for stored secrets like API keys. But until now, Swift developers have had to wire up each source individually…
🔥4 2
В продолжение рассмотренных тем касающихся систем сборки:
В 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
Telegram
YDC — Pizza Powered iOS
😃 Tuist снова завозит магию.
Вышла статья: “Teaching AI to read Xcode builds” - и ребята опенсорсят fork Swift Build Service под названием argus.
Это команднй интерфейс для AI-агентов, который позволяет разбирать, понимать и оптимизировать Xcode-сборки.…
Вышла статья: “Teaching AI to read Xcode builds” - и ребята опенсорсят fork Swift Build Service под названием argus.
Это команднй интерфейс для AI-агентов, который позволяет разбирать, понимать и оптимизировать Xcode-сборки.…
Иногда одна статья хорошо подсвечивает, насколько 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
Medium
Swift and Firebase: Managing Notification Sounds Based on App Settings With Source Code
Notification Service Extension and App Groups Usage
🔥9❤3
Почитал интересную статью от Two Cent Studios про контейнер Group в SUI – и она очень точно формулирует проблему, с которой многие сталкивались, но не сразу могли понять.
В 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, особенно при условиях
Код выглядит компактно, но становится менее предсказуемым.
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
💯5❤3🔥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 минут вместо нескольких спринтов самостоятельной разработки. Но за этим стоят множественные скрытые риски. Разработчики часто идут на это из-за жёстких дедлайнов, сложности задачи или давления бизнеса и не всегда задумываются о долгосрочных последствиях
🔺 Новые неожиданные баги с обновлениями версии 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
🔥5❤3 2
Попытка сделать быстрые инкрементальные билды для 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
@samwize
Incremental iOS Builds with Claude Code and XcodeBuildMCP
When using Claude Code for iOS development, raw xcodebuild commands are slow. While xcodebuild does support incremental builds, it’s not optimized for speed.
❤2 2
Казалось бы, тема пройдена вдоль и поперек, однако на технических интервью я периодически встречаю недопонимание принципов работы ARC даже у опытных разработчиков
⚡️Самый важный момент:
ARC "живет" только при компиляции
Он не отслеживает объекты в рантайме, не решает, когда освобождать память. Его задача - вставить в скомпилированный код вызовы функций, которые при MRC в Objective-C разработчик расставляет самостоятельно:
👉 objc_retain(ptr) - увеличивает счетчик ссылок объекта
👉 objc_release(ptr) - уменьшает счетчик
👉 objc_autorelease(ptr) - отложенное уменьшение счетчика, сегодня редкий кейс, об этом чуть ниже
Роль рантайма же - слепое исполнение инструкций. Если счётчик достигает нуля, объект немедленно деаллоцируется: вызывается deinit, освобождаются stored-свойства, память возвращается в кучу.
Что до счётчика ссылок - он хранится в заголовке объекта в куче и создаётся при аллокации объекта. Из Swift-кода доступа туда не получить
Используется редко, но стоит упомянуть в контексте 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
Medium
Understanding Autorelease Pool in Swift for iOS Development
What is an Autorelease Pool?
❤5🔥3 2 1
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
И начать год хочется с первой статьи — и снова про 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
Medium
The State of Agentic iOS Engineering in 2026
My perspective on AI-driven programming, workflows, and tooling
Если вы используете 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