YDC — Pizza Powered iOS – Telegram
YDC — Pizza Powered iOS
242 subscribers
65 photos
95 links
Young Da Code 👨‍💻
Первый командный дайджест о мобильной разработке 🍕
Download Telegram
🤖 🔐 Нативный способ борьбы с фродом на iOS: DeviceCheck (App Attest)

В iOS есть два системных механизма от Apple, которые реально помогают с анти-фродом — DeviceCheck и App Attest.

Оба — клиентские фреймворки. Они работают на устройстве и генерируют криптографические доказательства.
Сервер сам ничего «не проверяет» — он просто отправляет эти данные в Apple и уже по ответу решает, что делать дальше.

📱 DeviceCheck
Позволяет понять, что запрос пришёл с реального устройства и пользователь не пытается подделать свою активность.
- Выпускаем ключ для приложения на developer.apple.com
- Клиент в рантайме получает deviceToken через DeviceCheck API
- Сервер валидирует его через Apple и может читать/писать два бита состояния, которые Apple хранит для пары устройство + приложение (подписывая с помощью jwt).

Типичные кейсы:
- «один бонус на устройство»
- пометить девайс как подозрительный
- soft-ban без аккаунта

🔐 App Attest
Решает другую задачу (аналогичную deprecated ручке v1/validate_device_token) — подтверждает, что запрос идёт от оригинального приложения, а не от модифицированного.
- Добавляется новый капабилити
- Получается ключ (создаётся внутри Secure Enclave, наружу не экспортируется) для генерации nonсe с бекенда
- Генерируется обьект attestation на основе приватного ключа и nonce и отправляется на бекенд для дальнейших проверок
- Далее с помощью приватного ключа и nonсe генерируются assertion для отправки на сервер и верификации приложения

Application даёт сигнал, Apple — источник доверия, Backend принимает бизнес-решение.

P.S.: Ну и как всегда в разрезе security - оговорки. Jailbreak - все сломает (улучшайте jailbreak-detection), SSL-pinning поможет повысить защиту, скрывайте секреты, используйте обфускацию и шифрование.

#L #Security #AntiFraud #DeviceCheck #iOS

👏
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
🔥442
☝️ В модульных iOS-приложениях важно понимать как именно линкуются модули.

Существует 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
🔥7
😄 Когда хочется и новый стек трогать и легаси сильно не шатать

Если коротко, то тут статья, а тут макрос, который сгенерирует 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: Выключает проверки безопасности для лучшей производительности.

Плюсы:

↗️ Минимальные изменения в существующих модулях и обратная совместимость.

↗️ Пошаговая миграция: можно переводить отдельные вызовы/фичи.

↗️ Автоматизация через макросы уменьшает рутину и шанс ошибок.

↗️ Команда может продолжать продуктовую разработку параллельно с миграцией.

Минусы?

↘️ async/await обычно используют с throws, что даёт лаконичную обработку do/try/catch. Если старый нетворкинг возвращает Result<Response, Error>, то простая обёртка async -> Result не даёт преимуществ throws, клиенты всё равно будут делать switch/case или разбирать результат вручную.

↘️ resume нужно вызвать ровно один раз. Смешанная логика (ошибка сети + таймаут + cancellation + повтор попытки) повышает риск двойного resume или забытого resume, а это либо краш, либо подвисший await.

↘️ сам withCheckedContinuation имеет небольшой накладной расход и массовое применение без профилирования может дать неожиданный overhead. UnsafeContinuation быстрее, но теряет проверки.

🐊 Лично мне кажется, что на проекте с большим количеством легаси апи стоит с осторожностью внедрять такого рода кодогенерацию. С первого взгляда кажется удобным, но на деле может только добавить проблем. И было бы неплохо дописать макрос для нескольких реализаций метода с возвратом Result и с обработкой ошибок через throws.

📎 Modern Concurrency and Legacy code

#D #Arch #Legacy #Macros

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🦾 Новый open-source навык для SwiftUI и AI-агентов

Если вы уже используете AI-агентов для генерации SwiftUI, то наверняка сталкивались с тем, что код получался компилируемым, но не вполне «идентичным» SwiftUI — неэффективные паттерны, странные навигации или обновления состояний. Многие инженеры отмечают, что AI-помощники часто не понимают тонкостей SwiftUI и генерируют почти SwiftUI, который приходится вручную править и рефакторить.

В новой статье от Antoine van der Lee анонсирован SwiftUI Agent Skill open-source навык для AI-агентов, который помогает писать, улучшать и рефакторить SwiftUI-представления по лучшим практикам Apple.

🔍 Что такое Agent Skills?
Это пакеты с подробными инструкциями и контекстом по предметной области (в данном случае SwiftUI), которые AI-агент может «подгружать» и использовать при генерации/анализе кода, вместо того чтобы полагаться только на базовую модель. Такая система снижает количество повторяющихся ошибок и делает выводы агентов более осмысленными.

📌 В Skill есть подробные референсы по:
• оптимизации изображений и layout-паттернам;
• правильной композиции view;
• управлению состоянием и производительности;
• современным API и паттернам навигации.

💡 Это отличный шаг к тому, чтобы AI-агент не просто генерировал SwiftUI, а генерировал его правильно — с учётом архитектурных рекомендаций и практик сообщества.

#L #AI #SwiftUI

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
😏 Хочу разобрать статью про переход на Observation в SwiftUI и напомнить, зачем вообще появился этот механизм и чем он отличается от привычного ObservableObject.

Тема не новая, но на практике до неё доходят не сразу, особенно если в проекте уже есть устоявшийся подход к работе с состоянием.

🔹 Начиная с iOS 17 в SwiftUI доступен фреймворк Observation, который позволяет отслеживать изменения состояния без использования ObservableObject, @Published и Combine.

Основная идея – упростить работу с состоянием и сократить шаблонный код.

🔹 Классический подход с ObservableObject работает, но имеет свои особенности:
• необходимость явно помечать свойства как @Published
• дополнительный синтаксический шум
• риск забыть опубликовать изменения
• привязка к Combine даже в простых сценариях

Observation предлагает более прямой способ описывать наблюдаемое состояние.

🔹 На уровне кода вместо ObservableObject используется атрибут @Observable.

Старый подход:
class Counter: ObservableObject {
@Published var value = 0
}


С Observation:
@Observable
class Counter {
var value = 0
}


🔹 Преимущества такого подхода:
• Нет необходимости писать @Published, objectWillChange и вспомогательные конструкции.
• Меньше риска ошибок, связанных с ручным управлением публикацией изменений.
• Логика наблюдения находится ближе к самой модели.

Пример использования:
@Observable
class TimerModel {
var time: Int = 0

func tick() {
time += 1
}
}


Использование во View:
struct TimerView: View {
@State private var model = TimerModel()

var body: some View {
Text("Time: \(model.time)")
}
}


SwiftUI отслеживает изменения time и обновляет View без дополнительной настройки.

🔹 Где Observation особенно уместен:
• простые ViewModel и модели состояния
• логика, не требующая Combine
• случаи, где ObservableObject использовался только ради обновления UI

Следующие механизмы продолжают работать как раньше:
@State
@Binding
@EnvironmentObject

Observation не заменяет их, а дополняет.

🍕 Observation упрощает работу с состоянием в SwiftUI за счёт уменьшения шаблонного кода и более прямого описания наблюдаемых моделей. Для новых экранов и при постепенном рефакторинге старых ObservableObject это часто более удобный и читаемый вариант.

#R #SwiftUI #Observation
Please open Telegram to view this post
VIEW IN TELEGRAM
32🔥211
🦾 Автоматика подъехала: Опыт Tuist-а, где Codex мигрирует проект на кодген и поддерживает кеширование.
+ Tuist превращает все это дело в skill 🛠️

📦 Миграция Mastodon iOS
🎮 Первый skill — migrate

#L #Tuist #AI

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
73🔥1
🤖 📡 Базовые протоколы клиент-серверного взаимодействия (без обратной связи)

Хочется сделать серию постов по основам CS и system-design.
Если будет отклик, масштабируем в mind-map.
И начать хочется с сетевого взаимодействия.

Когда мы говорим про клиент-серверные запросы в большинстве приложений, мы почти всегда имеем в виду модель requestresponse.
Важно сразу зафиксировать: это не всегда про 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
- gRPCHTTP
- 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
🔥542
🫡 ⚠️ Warning. Expensive. Experimental.

В Claude Code появилась экспериментальная фича Agent Team.
Что позволяет запускать виртуальную команду ИИ-сессий, которые работают параллельно над одной задачей, берут задачи из общего пула и могут общаться между собой напрямую.
- можно распараллеливать работу по пуллу задач,
- тимейты говорят друг с другом и сами решают, что делать дальше,
- и могут критиковать друг друга,
- полезно для сложных фич, исследований и коворкинга с ИИ.

Но:
💸 дорого — каждый агент работает как отдельная сессия и "жжёт" токены,
🧪 экспериментально — фича отключена по умолчанию, поэтому, наверное, пока стоит осторожно.

#L #AI #Agent #Team

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
11
😏 Снова громкий заголовок – «Combine умер?», решил коротко разобрать статью и понять причину хайпа.

Повод - system prompt внутри Xcode AI, где есть рекомендация избегать Combine и предпочитать async/await. В system prompts Xcode есть строка:

“Avoid using the Combine framework and instead prefer … async and await”

Репозиторий с prompt’ами:
https://github.com/artemnovichkov/xcode-26-system-prompts

Это не документация Apple, а рекомендация для генерации нового кода. Но направление развития технологий читается довольно явно.

Apple уже несколько лет двигает стек в сторону async/await, Task, Actor и AsyncSequence. Они лучше встроены в язык, проще читаются и требует меньше шаблонного кода. Новые API чаще строятся вокруг concurrency-модели.

Combine никуда не делся. Он не deprecated, не удалён из SDK и используется в продакшене. Срочно переписывать существующий код смысла нет, но, очевидно, дефолтный выбор для нового async-кода сместился в сторону Structured Concurrency.

#R #Swift #Concurrency #Combine

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
💯2
Вечернее-занимательное чтение.

Пишет iOS разработчик с опытом, обзор на пост от iOS разработчика с опытом. 😅

Многие часто говорят про work-life balance, выгорание и т.д.
И по-моему для офисных работников и в т.ч. разработчиков это действительно важно.
Иногда мало-активный образ жизни, иногда дефицит прогулок и солнца могут приводить к утомлению и моральному, и физическому, особенно, на фоне большого количества интеллектуальной активности на работах.

Как-то после тяжёлой тренировки в зале у меня «поехала» спина.
Итог — несколько месяцев лечения грыжи у очень сильных врачей по резорбции.
Многое узнал про восстановление, но один мотив шёл через всё лечение красной нитью: витамин D в нормальных (иногда ударных) дозах реально ускоряет заживление, снижает воспаление и положительно влияет на самочувствие в целом.


Теперь про пост и занимательные выводы по географии, и почему большинству не хватает витамина D.

• Нью-Йорк ≈ 40,7° северной широты (место жительства автора)
• Москва ≈ 55°
• Астрахань ≈ 46° (моя родина)

Исследование которое дает автор:
Чем дальше от экватора — тем хуже коже удаётся синтезировать витамин D из солнца.

Зимой в Москве UVB почти нет вообще.
В Нью-Йорке солнца больше чем в МСК, сезон длиннее, но зимой дефицит тоже обычное дело.
В Астрахани лучше, но в зимнее время, далеко не идеально.

Отсюда и реальность: в Нью-Йорке есть проблемы, в МСК будет и подавно (с Астраханью сравнивать сложнее, солнца больше, но если верить статье про "усвоение", количество != качество).

Мне врачи рекомендовали ударные дозы витамина D в день, для коррекции дефицита — и судя по всему, это распространённая практика, особенно осенью и зимой.
Имхо, с дозировкой, конечно, лучше не гадать, а сдавать анализы и обсуждать с врачом.

Если коротко:
меньше солнца → меньше витамина D → хуже восстановление, иммунитет и общее самочувствие.
А мы тут живём не на экваторе.

#L #WorkLife #Health #Balance

👏
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥11