iOS Broadcast – Telegram
iOS Broadcast
3.46K subscribers
1.89K photos
86 videos
1.06K links
Подборка новостей и статей для iOS разработчиков.

Новости Kotlin и мультиплатформы @kotlin_broadcast
Новости Android @android_broadcast
Реклама и прочее @ab_manager
Download Telegram
🔨 Stanford CS193p Лекция 5
Первые дни новогодних праздников позади, а значит пора возвращаться к контенту. Что может быть лучше для начала года чем лекции Стенфорда. Пятая лекция сосредотачивается на архитектуре приложений, модели состояния и связке с UI — это следующий логичный шаг после первых четырёх лекций

🔵Глубокая архитектура приложения — как строить устойчивые, масштабируемые структуры, где Model, ViewModel и View чётко разделены.
🔵Связь модели и UI — через @StateObject, @ObservedObject, @Binding и реактивное обновление View.
🔵Swift Type System в архитектуре — как использовать enum, структуры и Optional для описания состояния приложения
🔵Обработка пользовательских событий — обновление модели, навигация, состояние побед/ошибок.
Все эти подходы помогают перейти от простого UI к полноценному приложению с бизнес-логикой, состояниями и тестируемой моделью

Почему это полезно?
🟡Если вы строите серьёзные приложения на SwiftUI, важно не только знать синтаксис, но уметь проектировать архитектуру
🟡Эта лекция показывает best practices по организации кода, которые работают и для небольших MVP, и для крупных приложений с десятками экранов
🟡Контент из Stanford — один из самых авторитетных источников входа в изучение SwiftUI и архитектуры iOS-приложений

#cs193p
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13
iOS Broadcast
🔨 Stanford CS193p Лекция 5 Первые дни новогодних праздников позади, а значит пора возвращаться к контенту. Что может быть лучше для начала года чем лекции Стенфорда. Пятая лекция сосредотачивается на архитектуре приложений, модели состояния и связке с UI —…
🔨 Stanford CS193p Лекция 6
Новая лекция из курса iOS Development with SwiftUI от Stanford University продолжает тему архитектуры приложений на SwiftUI — от базового разделения Model/View/ViewModel к более сложным паттернам устойчивости и масштабируемости. Лекция полностью состоит из демонстрации, на основе которой после лекции формируется домашнее задание.

Продвинутая архитектура SwiftUI-приложений:
🔵Управление состоянием на уровне всего приложения
🔵Организация логики и зависимостей через Observable, @MainActor, ViewModels
🔵Стратегии для больших проектов (модули, слои, separation of concerns)

Связь Model ↔️ ViewModel ↔️ View
🔵Обновление UI через реактивные свойства (@Published, Binding, @StateObject)
🔵Продвинутые паттерны: сценирование, flows, экраны со сложным состоянием

Работа с навигацией и состоянием
🔵Управление переходами в больших приложениях
🔵Сохранение состояния при смене экранов / вкладок

Домашнее задание:
Создать игру, похожую на CodeBreaker (которую создают в курсе), но с буквами английского алфавита вместо цветных меток, а также со следующими требованиями:
🟢Код и попытки должны быть словами на английском языке. Поэтому в игре используются все 26 букв алфавита как возможные «пины»
🟢UI должен показывать точные и неточные совпадения прямо на буквах (не через отдельные индикаторы)
🟢Кнопки должны быть расположены в виде QWERTY-клавиатуры, чтобы пользователь мог выбирать буквы
🟢Игра должна поддерживать перезапуск, выбор длины слова (от 3 до 6 букв), анимации из предыдущих лекций

#cs193p
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
2
🎯 Agent Skills: отказ от AGENTS.md в пользу переиспользуемых знаний для AI-агентов
Оказывается есть аналог глобального AGENTS.md для каждого проекта. Можно настроить общие подходы через скилы.

Skills заменяют AGENTS.md
🔵AGENTS.md — это единый файл с правилами/правилами для вашего AI-агента, но он обычно включает много проект-специфичной информации, которую трудно переиспользовать
🔵Agent Skills — это отдельные, тематические блоки знаний, хранимые в своих папках и которые можно подключать к разным проектам и инструментам

Skill — это каталог, содержащий:
🔵SKILL.md — файл с описанием навыка / инструкциями.
🔵references/ — дополнительные справочные материалы.
🔵noscripts, assets — вспомогательные файлы, шаблоны и прочее

Skills позволяют разделять знания по темам, например:
➡️Swift Concurrency
➡️Testing Patterns
➡️SwiftUI Best Practices
➡️Refactoring Guidelines
и использовать их во всей своей экосистеме AI-инструментов

Автор создал Swift Concurrency Skill с модульной структурой:
swift-concurrency/
├── SKILL.md
└── references/
├ async-await-basics.md
├ actors.md
├ tasks.md
├ memory-management.md
└ …

Это даёт агенту глубокий, структурированный контекст, когда он отвечает на вопросы или делает refactor/анализ кода

Преимущества подхода
🔵Повторное использование: навыки можно применять во многих проектах — больше не нужно копировать и править AGENTS.md в каждом
🔵Структурированность: навыки маленькие, тематические, легче поддерживаются
🔵Поддержка инструментов: многие инструменты (например Claude/Claude Code, Cursor) уже поддерживают стандарт Skills, а стандарт открыт
🔵Более качественные ответы: агенту легче выбирать и подгружать только нужные знания, чем держать весь контекст в одном AGENTS.md

Agent Skills эффективно превращают набор практик и знаний вашего стека в модульные, переиспользуемые блоки. Это даёт:
меньше дублирования
лёгкую поддержку и обновление знаний
более точные ответы от AI-агентов
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🎯 Privacy как бизнес-модель Apple
Google и Apple опубликовали совместное заявление, что само по себе редкость. Компании подчеркнули общее видение будущего цифровой экосистемы - AI с акцентом на безопасность, приватность и ответственность крупных платформ.
Факт - бизнес Apple не строится на продаже пользовательских данных

Именно поэтому Apple может:
🔵Выстраивать маркетинг вокруг privacy
🔵Делать privacy частью позиционирования платформы
🔵Использовать privacy как конкурентное преимущество

Для компаний, живущих за счёт рекламы и данных, такой подход просто недоступен.
На этом фоне совместное заявление Apple и Google выглядит не компромиссом, а расчётливым шагом:
📁 Apple не продаёт данные — Apple продаёт устройства, экосистему и доверие.
🧰 Google нуждается в сильном партнере для соперничества с OpenAI и Anthropic

Gemini — один из самых зрелых AI-стеков
🔵сильная работа с контекстом и мультимодальностью
🔵быстрый цикл улучшений и масштабируемость

И ключевое — Gemini легко встраивается как внешний сервис, без передачи контроля над платформой.

Apple делает то, что умеет лучше всего:
🔵чётко очерчивает границы доступа
🔵изолирует внешние модели от пользовательских данных
🔵оставляет UX и data-flow под своим контролем

Gemini здесь — инструмент, а не хозяин экосистемы.

Apple усиливает платформу, используя privacy как рычаг, а Gemini — один из немногих AI-партнёров, которого можно встроить, не ломая эту модель.
Верите в успех этого партнерства или расстроены тем что Apple признали свое отставание и сдались вендору в плоскости AI?
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🔨 Creating reminder lists with EventKit (и зачем это вообще нужно)
Добавить напоминание в дефолтный список — легко.
Но как только у вас появляются кейсы типа Проекты / Контексты / Приоритеты, всё ломается:
🟣Пользователю некуда "складывать" задачи из вашего приложения
🟣Получается помойка в одном списке
🟣Вы теряете смысл интеграции с системными Reminders

Искушение: писать в default list и забыть
🔴 EventKit позволяет быстро сохранить EKReminder в defaultCalendarForNewReminders() — и кажется, что задача решена. Но это не UX, а технический костыль.

Рабочий подход: создавать свои списки (reminder lists) через EKCalendar
🟢В этом случае напоминания живут внутри календария для reminders (EKCalendar c entity .reminder)

Что делаем:
🔵Запрашиваем доступ к Reminders через requestFullAccessToReminders()
🔵Загружаем текущие списки: eventStore.calendars(for: .reminder)
🔵Создаём новый список: EKCalendar(for: .reminder, eventStore: ...), задаём noscript, подбираем source, сохраняем saveCalendar(..., commit: true)
🔵Добавляем напоминания в выбранный список через EKReminder, выставляя dueDateComponents и сохраняя eventStore.save(reminder, commit: true)
🔵Важно: не забыть ключ в Info.plistPrivacy - Reminders Full Access Usage Denoscription.

Списки Reminders должны сохраняться в конкретное хранилище (локально / iCloud / CalDAV). Авторы предлагают приоритет:
🟢.local или .calDAV, иначе fallback на defaultCalendarForNewReminders()?.source
🟢Если вы добавляете Reminders “как интеграцию” — делайте списки, иначе это просто запись в чужой inbox.
🟢Если у фичи есть доменная структура (проекты/категории) — отражайте её системными списками.
Please open Telegram to view this post
VIEW IN TELEGRAM
🗞 Дайджест новостей для iOS разработчиков за январь
Небольшие но важные изменения к которым нужно подготовиться:
🔵iOS 26.3 beta 2. Apple выкатили beta версии 26.3, релиз совсем скоро, самое время прогнать тесты
🔵App Store комплаенс — важные дедлайны
🔴Age Rating: до 31 января 2026. Рейтинги приложений автоматически “пересчитали” под новую систему, но вам нужно ответить на обновлённые вопросы в App Store Connect до 31.01.2026, иначе можно словить блок при отправке апдейтов
🔴Техас: возраст, согласия, PermissionKit. С 1 января 2026 для новых Apple Accounts в Техасе включаются требования по age assurance и parental consent (до 18 лет) — Apple даёт API для получения возрастной категории.
🔴EU: новая модель условий и UX установки
🔴Корея Sign in with Apple: новое требование (с 1 января 2026). При регистрации/обновлении Services ID нужно указывать endpoint для server-to-server нотификаций
🔵Swift 6.2.3 вышел в декабре, а в январе уже доступны снапшоты ветки release/6.3. В 6.2 заметно прокачали “approachable concurrency” (включая режимы изоляции), добавили опции для более строгой memory safety, ускорили сборки проектов с макросами (prebuilt swift-syntax) и продолжают развивать экосистему библиотек/тестов
Please open Telegram to view this post
VIEW IN TELEGRAM
🈸 StoreKit 2: как давать доступ к premium-фичам (и не сломать уровни подписки)
Не часто приходится работать с in-app-ми и это то место, в котором не хочется допускать ошибки. Тут и репутационные и финансовые риски. Особенно сложно работать с нескольими уровнями подписок: как только вы добавляете несколько тарифов (например, личный / семкйный + месяц / год), появляются типичные боли:
🔵Приложение не понимает “какой план активен”, когда есть overlap при апгрейде/даунгрейде
🔵UI не может честно показать “что сейчас” и “на что продлится”
🔵Транзакции прилетают повторно / ennoscriptment “откатывается” после рестарта

Подход из статьи: “всегда выбираем самый высокий tier”
1) Группы подписок + уровни (Level of Service)
Apple использует “Subnoscription Level” (lower number = *higher tier*) для логики апгрейдов/даунгрейдов и того, какая подписка должна считаться активной
В примере:
🟢Family = level 1 (выше)
🟢Individual = level 2 (ниже)
🟢Monthly и Yearly одного тира должны иметь одинаковый level, чтобы это был тот же tier, другая периодичность.

2) Модель тиров в коде
Делаем enum PassStatus (notSubscribed / individual / family) и маппим productID → tier, чтобы интерпретировать статусы StoreKit

3) Вычисляем текущий доступ по status’ам
Фильтруем statuses до .subscribed и выбираем max tier (чтобы Family “перебивал” Individual при overlap)

4) Trust only verified
Только .verified транзакции считаем ennoscriptment’ом. Если verification не прошёл — считаем “нет подписки”.

5) Обязательно finish + наблюдаем апдейты
🟢Каждую verified транзакцию нужно finish(), иначе StoreKit может принести её снова
🟢На старте проверяем Transaction.unfinished (после крэша/сети)
🟢Держим живым listener на Transaction.updates для мгновенного обновления UI

6) UI: SubnoscriptionStoreView + статус рядом
В статье используют SubnoscriptionStoreView(groupID:), а текущий tier и “renews to …” строят из renewalInfo.

Эмпирическое правило для подписок
🟢Ennoscriptment = verified transaction + правильно настроенный tier
🟢Тарифы = данные (ASC/StoreKit config), код должен лишь корректно их интерпретировать
🟢UI всегда показывает “effective tier”, а не последний купленный productID
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
📱 SwiftUI: как комбинировать жесты без магии и багов
Немного базы в пятницу, статья про жесты в SwiftUI.

Кейс один экран — несколько интеракций
Как только на элементе появляются drag + rotate + long press + tap — SwiftUI быстро начинает угадывать, какой жест вы имели в виду и не всегда у него это выходит успешно:
🔵Случайные конфликты распознавания
🔵Съеденные жесты
🔵Неочевидное поведение (особенно на трекпаде)
Все это создает негативный UX

🔴Искушение: повесить несколько .gesture(...) и надеяться... На что-то обычно заканчивается тем, что один жест побеждает всегда, а второй почти не срабатывает.

Три базовых композиции жестов в SwiftUI:

1️⃣In sequence — сначала один, потом второй
Кейс: long press → drag
Используем LongPressGesture(...).sequenced(before: DragGesture())
🔵сначала удержание (например 0.5s)
🔵если пользователь продолжает — начинается drag
Идея: @GestureState обновляется через .updating(), а drag-translation читаем в .onChanged() на втором этапе

2️⃣ Simultaneous — два жеста одновременно
Кейс: drag + rotate
DragGesture().simultaneously(with: RotateGesture())
🔵можно тащить и одновременно крутить (двумя пальцами)
🔵каждый жест обновляет своё состояние через .onChanged()

3️⃣ Exclusive — либо одно, либо другое
Кейс: tap vs long press
ExclusiveGesture(TapGesture(), LongPressGesture(minimumDuration: 1.0))
🔵сработает первый распознанный жест
🔵tap меняет цвет, long press — увеличивает scale

💡 Шпаргалка:
🔵Если жесты должны идти “как сценарий” → Sequence
🔵Если жесты независимы и должны работать параллельно → Simultaneous
🔵Если жесты конкурируют за одно и то же взаимодействие → Exclusive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🐚 Skip - плагин Xcode для транспиляции SwiftUI приложения на Android теперь Open Source
Я вам несколько раз рассказывал про Skip и о своих надеждах и сомнениях по поводу этого инструмента и пришли новости. Платно получать лок на вендора желающих достаточно не оказалось, но наработки пригодились Apple рабочей группе по Android.

📱 Проблема: cross-platform “без компромиссов” всегда упирался в доверие
Многие команды хотят Swift/SwiftUI → Android, но боятся строить стратегию на маленьком закрытом платном туле: “а если завтра rug pull / покупка / закрытие?”. Skip прямо называет этот страх ключевым барьером adoption.

Начиная с Skip 1.7:
🟢убраны все лицензии: никаких ключей, EULA, trial/period
🟢open-sourced “skipstone” — движок, который делает всю магию на build-time (плагины Xcode/SwiftPM, трансформация iOS→Android, bundling ресурсов/локализаций, JNI bridge, transpile, packaging, export)
🟢документация/сайт переезжают на skip.dev, тоже open source

Моя оценка Skip в 2026:
🔵 Если вам нужен shared Swift-стек (и вы готовы жить в мире “не все либы заведутся идеально с первого раза”) — Skip теперь реально стоит POC
🔵 Главный риск (закрытый платный core) — существенно снижен: foundation теперь открытый и бесплатный
🔴 Главный вопрос, а нужен ли он в мире с AI агентами, когда можно попросить создать нативное приложение под Android на основе исходников для iOS, пробовал кто-то?
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔6👍31🔥1
🎹 Liquid Glass «по-взрослому»: что делать, когда режим совместимости исчезнет
iOS 26 принёс Liquid Glass как новый визуальный слой системы. Первое время Apple дала “костыль” — compatibility mode, чтобы старый UI не «поплыл» сразу после перекомпиляции. Но ключевое слово тут — на первое время.

Когда перестаёт работать режим совместимости?
Сегодня (Xcode 26 / iOS 26) можно отложить новый дизайн через Info.plist ключ UIDesignRequiresCompatibility (UI Design Requires Compatibility). Donny Wals прямо пишет, что Apple планирует убрать эту опцию в следующем мажорном Xcode, и поэтому Xcode 27 вероятно сделает Liquid Glass обязательным

Дополнительно, на форумах Apple в обсуждениях этого ключа фигурирует предупреждение из документации:
Temporarily use this key while reviewing and refining your app’s UI for the design in the latest SDKs


То есть ставка на “оставим compat mode навсегда” — плохой план.
И ещё момент: compatibility mode уже может ломать поведение контролов (пример — баг с UISegmentedControl, который проявляется именно при включённом UIDesignRequiresCompatibility)

Стратегия миграции без боли:
🟢Dev-схема: Liquid Glass включён (без UIDesignRequiresCompatibility)
🟢Release-схема: compat mode включён пока мигрируете
🟢Как только готовы — убираете ключ и закрываете тему
Самый простой вариант — две Info.plist: Info-Dev.plist и Info-Release.plist, и переключение в Build Settings.

Начинайте не с карточек/экраников, а с того, что пользователь видит всегда:
🟢Tab Bar / Tool Bar / Navigation Bar
🟢Search / Large noscripts
🟢Sheets / Popovers / Alerts
🟢Scroll edge / Underlap / Safe areas
Цель: чтобы приложение выглядело органично *в рамках нового system look* — даже если ваш контент ещё не идеален.

Liquid Glass любит:
🟣слои
🟣прозрачность
🟣динамический фон

А ломает:
🔴мелкий текст на blur
🔴тонкие разделители
🔴кастомные цвета без учета системных материалов

Правило: переходите на системные семантические цвета/материалы там, где можно, а кастом оставляйте для контента.

Accessibility — обязательный прогон
🟡Reduce Transparency (особенно важно для “стекла”)
🟡Reduce Motion
🟡Dynamic Type (XL–AX)
🟡Increased Contrast / Bold Text
Иначе вы сделаете красиво, но сломаете читаемость для части пользователей.

⚠️ Когда Xcode 27 уберёт opt-out, останется два пути:

1. Принять Liquid Glass как новый baseline
🟢системные компоненты → выглядят по-новому
🟢ваш бренд → через контент, типографику, иллюстрации, spacing
🟢кастомный “старый iOS” не симулируете, иначе будете выглядеть “как чужой app”
Это путь с минимальными затратами и максимальной совместимостью.

2. Сделать свои компоненты
🟡вы пишете/поддерживаете кастомные компоненты (tab bar, nav bar, backgrounds)
🟡постоянно догоняете изменения системы
🟡рискуете UX/доступностью и конфликтами с платформенными паттернами
⚠️ Подходит только если у вас продукт, где дизайн — ключевой дифференциатор, и есть ресурс на поддержку.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
🔨 Geko - CLI для инфраструктуры разработки в Xcode-проектах
Большой релиз инструмента, который мы активно используем у себя внутри для работы с приложениями.

Когда у вас сотни/тысячи модулей, вы начинаете страдать от обвязки:
🔵Генерация .xcodeproj/.xcworkspace становится медленной
🔵Сборка ползёт из-за отсутствия нормального кэша между модулями
🔵Зависимости (Pods/SPM) превращаются в отдельный мир боли
🔵Любые нестандартные кейсы требуют костылей/скриптов

Решение: Geko
Geko — CLI-утилита для управления dev-инфраструктурой Xcode-проектов: DSL на Swift для описания структуры, генерация проектов и встроенная система кэширования.
Что есть из коробки:
🟢Swift-DSL для описания структуры проекта
🟢быстрая генерация .xcodeproj/.xcworkspace даже для тысяч модулей
🟢Build Cache: локальный + удалённый (S3-совместимый)
🟢Встроенный пакетный менеджер для CocoaPods + поддержка SPM
🟢plugin system под сложные кейсы
🟢Частичная поддержка Linux (под subset фич)

⚡️ Кэш: топ фича из коробки:
🔵Локально — можно стартовать без доп настроек
🔵Профили прогрева
🔵Удалённый кэш (S3)
Please open Telegram to view this post
VIEW IN TELEGRAM
11