В недавней демонстрации Apple показала нечто, что можно назвать настоящим прорывом в работе инструментов для разработки. В Xcode 26.3 программирование — это уже не просто более быстрое написание кода на Swift. Теперь среда разработки может делегировать целые инженерные задачи автономным агентам, которые планируют, выполняют и дорабатывают функции почти так же, как это делал бы младший разработчик.
Цель проста: опишите, что вы хотите создать, а система сделает всю механическую работу за вас.
🔹 От идеи до работающей функции
В видео Apple показывает пример приложения, в котором отображаются достопримечательности по всему миру. Вместо того чтобы собирать все вручную, мы можем попросить агента добавить данные о погоде в реальном времени с помощью WeatherKit и отобразить прогноз на семь дней в новом стиле Liquid Glass.
С помощью этого простого запроса Xcode и агент:
В итоге в приложении появилась полноценная функция отображения погоды, реализованная в нескольких новых файлах и сотнях строк кода.
Дело было не в самой генерации кода. Дело было в рабочем процессе. Агент вел себя как разработчик, который сначала изучает кодовую базу, затем решает, куда что добавить, а потом вносит изменения, если что-то не работает.
🔹 Xcode как платформа для автономных агентов
Это нововведение стало возможным благодаря тому, что Apple предоставила доступ к внутренним инструментам Xcode через открытый стандарт под названием Model Context Protocol. Теперь агенты могут не только угадывать ответы языковой модели, но и:
Тесная связь между интегрированной средой разработки и моделью делает возможными многоэтапные задачи. Агент не просто пишет код. Он использует настоящие инструменты разработчика.
Apple также разработала встроенную интеграцию с облачными агентами от Anthropic и OpenAI. Их можно загрузить прямо в Xcode и обновлять автоматически, при этом оптимизируется использование токенов и вызов инструментов.
🔹 Что это значит для iOS-разработчиков
Это переход от «ИИ как автозаполнения» к «ИИ как исполнителю».
Вместо того чтобы запрашивать функцию или представление, разработчики теперь могут описывать результаты.
Агент выполняет механические действия, в то время как человек сосредотачивается на принятии решений, связанных с продуктом, его архитектурой и анализом.
Это больше похоже на делегирование задач, чем на подсказки.
🔹 У IDE другое будущее
Идея Apple ясна: сама IDE становится координационным центром для интеллектуальных агентов. Окна чата уходят на второй план. Реальная разработка происходит внутри инструмента, а модели работают непосредственно с проектом.
Для команд, работающих с iOS, это может изменить подход к созданию прототипов функций, избавлению от шаблонного кода и ускорению процесса превращения идей в рабочий код.
То, на что раньше уходили часы, теперь можно сделать за считаные минуты — и сразу приступить к доработке, а не начинать с нуля.
Xcode 26.3 уже доступен, и агентное программирование официально стало частью рабочего процесса разработки Apple.
#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2😁1🥱1
Команда разработчиков языка программирования Swift представила Swift System Metrics 1.0 — инструмент для сбора системных метрик в серверных Swift-приложениях. Утилита доступна для macOS и Linux.
Swift System Metrics собирает базовые метрики процесса, включая нагрузку на CPU, потребление памяти, количество открытых файловых дескрипторов, установленный лимит файловых дескрипторов и время работы процесса. Авторы проекта отмечают, что этого набора метрик хватает для анализа производительности сервисов и потребления ресурсов.
Инструмент встраивается в экосистему Swift и передаёт собранные данные в Swift Metrics — общий API для работы с метриками. Благодаря этому разработчики могут экспортировать данные в сторонние системы визуализации и мониторинга, например, в Grafana, Prometheus и OpenTelemetry.
Для работы со Swift System Metrics надо сперва добавить зависимость в Package.swift и target:
.package(url: "https://github.com/apple/swift-system-metrics", from: "1.0.0");.product(name: "SystemMetrics", package: "swift-system-metrics").После этого инструмент можно экспортировать и использовать в коде проекта:
import SystemMetrics
import ServiceLifecycle
import Logging
import OTel
@main
struct Application {
static func main() async throws {
// Create a logger, or use one of the existing loggers
let logger = Logger(label: "Application")
// Setup MetricsSystem, for example using swift-otel
var otelConfig = OTel.Configuration.default
otelConfig.serviceName = "Application"
let otelService = try OTel.bootstrap(configuration: otelConfig)
// Setup your service
let service = FooService()
// Create the monitor
let systemMetricsMonitor = SystemMetricsMonitor(logger: logger)
// Create the service
let serviceGroup = ServiceGroup(
services: [otelService, service, systemMetricsMonitor],
gracefulShutdownSignals: [.sigint],
cancellationSignals: [.sigterm],
logger: logger
)
try await serviceGroup.run()
}
}
#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
App Store Connect CLI — быстрая, легковесная, со скриптами CLI-утилита для работы с App Store Connect API. Автоматизируйте рабочие процессы выпуска iOS, macOS, tvOS и visionOS из терминала, IDE или конвейера CI/CD. Работайте с TestFlight, сборками, отправкой, подписанием, аналитикой, скриншотами, подписками и многим другим. JSON-ориентированный подход, без интерактивных промптов.
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
Когда приложение начинает рендерить тяжёлые ленты, многократно парсить сложный текст или декодировать одни и те же ресурсы при каждом скролле, разница между «просто работает» и «работает плавно» часто кроется в правильно расположенном кэше.
На iOS для таких задач отлично подходит
NSCache из Foundation. Это in-memory контейнер с привычным key-value интерфейсом, но с одной важной особенностью: он автоматически удаляет элементы, когда системе не хватает памяти.🔹 Что такое NSCache и как он работает?
Похож на
Dictionary, но спроектирован специально для кэширования. Ключевое свойство — автоматическая эвикция (удаление) при нехватке памяти. Идеально подходит для объектов, которые дорого создавать, но безопасно пересоздать.Важные особенности:
AnyObject). Для value types нужна обёртка (класс).🔹 Практический пример: кэшируем NSAttributedString
Типичный сценарий — кэширование результатов парсинга Markdown/HTML в
NSAttributedString. Эта операция может быть очень дорогой, особенно с вложенными изображениями.final class AttributedStringCache {
private let cache = NSCache<NSNumber, NSAttributedString>()
init() {
cache.countLimit = 500 // Максимум 500 объектов
cache.totalCostLimit = 15 * 1024 * 1024 // Лимит памяти ~15 МБ
}
func get(for id: Int) -> NSAttributedString? {
cache.object(forKey: NSNumber(value: id))
}
func set(_ object: NSAttributedString, for id: Int) {
// В качестве cost можно использовать длину строки
let cost = object.length
cache.setObject(object, forKey: NSNumber(value: id), cost: cost)
}
}🔹 Где NSCache незаменим
Идеальные кандидаты:
NSAttributedString)UIImage)Правило простое: кэшируем то, что дорого производить, но безопасно пересоздать.
🔹 Где NSCake не нужен
Плохие кандидаты:
NSCache не умеет удалять по времениURLCache🔹 Почему NSCache — не сетевой кэш
NSCache не понимает HTTP-заголовки (Cache-Control, ETag), не сохраняет данные на диск и не умеет валидировать ответы. Для сетевого кэширования используйте URLCache с URLSession:let cache = URLCache(
memoryCapacity: 50 * 1024 * 1024,
diskCapacity: 200 * 1024 * 1024,
directory: .cachesDirectory
)
let config = URLSessionConfiguration.default
config.urlCache = cache
🔹 Важные советы по использованию
1. Настройте лимиты — без них
NSCache не будет удалять объекты, пока система не прижмёт.2. Не обрабатывайте memory warnings вручную —
NSCache сам реагирует на нехватку памяти. Ручная очистка removeAllObjects() по нотификации didReceiveMemoryWarning только мешает встроенной логике.3. Учитывайте thread-safety — сам
NSCache потокобезопасен для базовых операций. Но если вы добавляете поверх него свою логику (подсчёт попаданий, TTL), синхронизируйте её сами.4. Используйте cost осмысленно — это не обязательно байты. Для
NSAttributedString можно брать длину или добавлять коэффициенты за вложения.🔹 Итог
NSCache — один из самых чистых способов внедрить некритичное in-memory кэширование. Он быстрый, потокобезопасный и автоматически адаптируется к состоянию памяти.Используйте, когда:
Избегайте, когда:
Правильно встроенный
NSCache часто убирает пики повторной обработки данных и рывки при скролле, оставаясь при этом гибким под нагрузкой.#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
SwiftUI Pro — агентский навык, помогающий ИИ-помощникам писать более умный, простой и современный SwiftUI, с рекомендациями по использованию API, дизайну, производительности и доступности. Охватывает навигацию, компоновку, анимацию, управление состоянием, VoiceOver, устаревшие API и многое другое, ориентируясь на ошибки, которые действительно допускают программисты с большим опытом.
Навык основан на рабочем файле АGENTS. md, а это значит, что вы можете привнести многолетний опыт и знания в выбранного вами агента всего за несколько минут. Он использует формат Agent Skills, поэтому бесперебойно работает с Claude Code, Codex, Gemini, Cursor и другими.
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
При разработке iOS-приложений часто нужно привести приложение к определённому состоянию — например, для воспроизведения бага или тестирования граничных случаев. LLDB предоставляет мощный инструмент: команду
expression (или её короткую форму expr), которая позволяет изменять значения прямо во время выполнения, не касаясь исходного кода и не перезапуская приложение.🔹 Изменение значений из консоли
Когда приложение останавливается на брейкпоинте, можно использовать консоль Xcode, чтобы изменить переменную в нужное состояние.
Представьте, что мы исправляем баг, который воспроизводится только для птиц со статусом «на грани исчезновения». Когда брейкпоинт срабатывает на нужной строке, сначала можно вывести текущий статус:
(lldb) po bird.conservationStatus.title
"endangered"
Чтобы протестировать с другим статусом, используем
expr:(lldb) expr bird.conservationStatus = .cr
Проверяем:
(lldb) po bird.conservationStatus.title
"critically endangered"
После этого можно продолжить выполнение и наблюдать, как приложение ведёт себя с изменённым состоянием. Это особенно полезно, когда баг проявляется только в редких условиях, которые сложно воспроизвести иначе.
🔹 Когда это полезно
На практике есть и другие способы — например, просто захардкодить нужное значение прямо в коде (и не коммитить это изменение). Такой подход часто проще и понятнее, особенно с учётом системы типов Swift.
Модификация состояния через LLDB становится полезной, когда воспроизведение определённого состояния требует много времени или усилий. Например, вы уже находитесь на нескольких экранах вглубь навигационного потока и хотите протестировать конкретный граничный случай. Вместо того чтобы перезапускать приложение и заново проходить весь путь, можно изменить состояние прямо на брейкпоинте:
expr result = .error
Этот подход также удобен для экспериментов с разными значениями во время отладки. Вместо многократной смены кода и пересборки можно быстро перебрать разные сценарии:
expr config.isEnabled = false
🔹 Oграничения
Несмотря на мощность этого инструмента, есть несколько важных ограничений:
let) изменять нельзя — попытка присвоить новое значение вызовет ошибку.🔹 Автоматизация изменений с помощью действий брейкпоинта
Когда при воспроизведении бага нужно, чтобы переменная всегда имела определённое значение, можно настроить автоматическое действие на брейкпоинте:
1. Установите брейкпоинт в нужном месте
2. Нажмите правой кнопкой на брейкпоинт и выберите Edit Breakpoint
3. Добавьте действие типа Debugger Command
4. Введите команду:
expr bird.conservationStatus = .cr
5. Включите опцию Automatically continue after evaluating actions
Теперь каждый раз, когда срабатывает этот брейкпоинт, LLDB автоматически применяет изменение и продолжает выполнение. Это позволяет последовательно воспроизводить нужный сценарий без ручного вмешательства.
🔹 Итог
LLDB — это не только просмотр переменных, но и мощный инструмент для активного изменения состояния приложения во время отладки. Команда
expr позволяет:Помните про ограничения (константы, value types, SwiftUI-свойства), но в остальном — это отличный способ ускорить отладку и тестирование.
#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
CocoaLumberjack — это быстрая и простая, но при этом мощная и гибкая платформа для ведения логов, предназначенная для macOS, iOS, tvOS, watchOS и visionOS.
Фичи:
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩1😍1
При работе с in-app покупками тестирование различных сценариев — важная часть разработки. StoreKit предоставляет локальную среду, которая позволяет симулировать покупки, подписки и краевые случаи без подключения к App Store Connect.
🔹 Обзор процесса
Чтобы тестировать покупки локально, нужно:
1. Создать и настроить StoreKit configuration file
2. Включить StoreKit testing в Xcode
3. Симулировать покупки и управлять транзакциями
🔹 StoreKit configuration files
Файл конфигурации (
.storekit) определяет продукты и поведение подписок для локальной симуляции. StoreKit читает этот файл вместо общения с App Store.Xcode поддерживает два типа файлов:
🔹 Создание конфигурационного файла
Xcode предоставляет встроенный шаблон для создания
.storekit файла. При именовании полезно использовать описательное название, например StoreKitConfigurationLocal.storekit.Для локальной конфигурации можно вручную добавлять продукты через кнопку +: consumables, non-consumables, auto-renewable subscriptions и non-renewing subscriptions. Для каждого продукта задаётся идентификатор, цена и длительность подписки.
Для синхронизированной конфигурации при создании выбирается приложение и команда для синхронизации. Xcode зеркалирует существующую конфигурацию. Такие файлы полезны для тестирования продакшн-настроек.
🔹 Включение StoreKit testing
После создания файла нужно прикрепить его к схеме приложения. В редакторе схемы выбирается конфигурационный файл. После этого все StoreKit-запросы разрешаются через выбранный файл вместо App Store. Чтобы отключить локальное тестирование, установите значение обратно в None.
🔹Тестирование покупок
После включения StoreKit testing покупки можно запускать прямо в приложении. С точки зрения кода ничего не меняется — StoreKit ведёт себя как при общении с App Store, но ответы генерируются локально.
Это позволяет тестировать:
Всё работает быстро и повторяемо.
🔹 Управление транзакциями
Xcode предоставляет инструменты для контроля транзакций во время тестирования. Открыть менеджер транзакций можно:
Debug → StoreKit → Manage Transactions в меню XcodeОтсюда можно:
Это позволяет воспроизводить краевые случаи, которые сложно протестировать через App Store sandbox.
🔹 Итог
StoreKit testing позволяет симулировать in-app покупки прямо в Xcode без внешних систем. Определив продукты в конфигурационном файле и прикрепив его к схеме, можно быстро тестировать сценарии покупок и сократить цикл обратной связи.
Перед релизом приложения всё равно важно протестировать через App Store sandbox для проверки реального поведения.
#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉1
Каждый опытный iOS-инженер рано или поздно сталкивался с этим: вы возвращаетесь с экрана, ожидаете вызова
deinit, но ничего не происходит. Вью исчезло, а память — нет.В SwiftUI такая проблема регулярно всплывает у трёх модификаторов:
onSubmit, searchable и refreshable. Экран внутри NavigationStack имеет свою вью-модель, вы возвращаетесь назад, а вью-модель остаётся жить.Разберём, почему это происходит и как это чинить.
🔹 Случай с
onSubmitМинимальный пример:
NavigationStack {
NavigationLink("Push") {
DetailView()
}
}
struct DetailView: View {
@State private var viewModel = DetailViewModel() // 👈 Потенциальная проблема
var body: some View {
TextField("Text", text: $viewModel.text)
.onSubmit {
viewModel.performSmth()
}
}
}После сабмита и возврата назад
deinit не вызывается.Две возможные причины:
1. Неверное управление жизненным циклом. Хранение ObservableObject в @State даёт непредсказуемую семантику владения. @StateObject был создан именно для того, чтобы дать SwiftUI стабильную идентичность объекта.
2. Утечка на уровне фреймворка. onSubmit связан с текстовой системой UIKit. Если SwiftUI или UIKit удерживают обработчик дольше, чем нужно, замыкание держит вью-модель.
Что делать:
.onSubmit { [weak viewModel] in
viewModel?.performSmth()
}🔹 Комбинация
searchable + refreshableЕщё один известный кейс: вместе эти модификаторы могут удерживать вью-модель, особенно в связке с
ScrollView и NavigationStack.Проблема проявляется не всегда. Иногда объекты деаллоцируются позже, после дополнительных навигаций или принудительной памяти. Воспроизводимость зависит от версии ОС, контейнера и структуры навигации.
🔹 Retain cycle внутри замыканий
Прежде чем винить SwiftUI, проверьте классические захваты:
.refreshable {
await viewModel.reload() // сильный захват self
}Если
reload() создаёт долгоживущую задачу, а замыкание остаётся удержанным иерархией вью — образуется цикл.Решение — weakening:
.refreshable { [weak viewModel] in
await viewModel?.reload()
}🔹 Влияние NavigationStack
NavigationStack сам по себе может удерживать части навигационного дерева для производительности и восстановления состояния. Исчезновение вью не всегда означает деаллокацию.При диагностике:
Если объект исчезает после последующих навигаций — это, вероятно, кэширование SwiftUI, а не утечка.
🔹 Правила, которые предотвращают большинство проблем
@StateObject. Экземпляр инжектится → @ObservedObject или var. Не храните ObservableObject в @State.onSubmit, refreshable и других замыканиях, которые могут удерживаться UI-инфраструктурой.🔹 Итог
SwiftUI даёт элегантные API, но всё ещё требует дисциплины в управлении памятью. Проблемы с
onSubmit, searchable и refreshable — не миф. Но в большинстве случаев они решаются правильным выбором property wrapper и ослаблением ссылок в замыканиях. А иногда — просто пониманием, что NavigationStack может кэшировать вью дольше, чем вы ожидаете.#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
При работе с большими наборами данных нет необходимости загружать их все сразу. Во многих случаях достаточно получить первую страницу результатов, а затем загружать контент по мере прокрутки.
List в SwiftUI хорошо подходит для реализации этого шаблона. В сочетании с асинхронной загрузкой и небольшим количеством состояний для разбивки на страницы мы можем создать предсказуемую бесконечную прокрутку без большого количества кода.В этом посте мы рассмотрим, как реализовать постраничную навигацию с помощью
List, загружая следующую страницу, когда пользователь доходит до конца списка.🔹 Обзор подхода
Пагинацию можно реализовать разными способами. В этой статье мы сосредоточимся на бесконечной прокрутке, при которой новый контент загружается автоматически, когда пользователь доходит до конца списка.
Простой и эффективный способ добиться этого — добавить специальную «строку загрузки» в конец списка.
Когда эта строка становится видимой, мы отправляем запрос на следующую страницу.
🔹 Реализация списка
Сначала мы отображаем текущие элементы и при необходимости добавляем строку загрузки:
List {
ForEach(viewModel.items, id: \.id) { item in
ListItemView(item: item)
}
if viewModel.isMoreDataAvailable {
lastRowView
}
}Основная идея заключается в том, что строка загрузки отображается только тогда, когда можно загрузить больше данных.
🔹 Запуск постраничной навигации
Строка загрузки отвечает за запуск запроса на следующую страницу, когда появляется на экране:
var lastRowView: some View {
ZStack {
switch viewModel.paginationState {
case .isLoading:
ProgressView()
case .error(let error):
ErrorView(error)
}
}
.frame(height: 50)
.onAppear {
viewModel.loadMoreItems()
}
}Когда пользователь прокручивает список до конца, эта строка становится видимой, и срабатывает ее модификатор
onAppear.В этот момент мы загружаем следующую страницу.
🔹 Управление состоянием разбивки на страницы
Строка загрузки также позволяет наглядно отобразить текущее состояние разбивки на страницы. Например, во время загрузки мы можем показывать индикатор выполнения или сообщение об ошибке с возможностью повторной попытки, если запрос не выполнен.
Это делает поведение предсказуемым и упрощает его расширение.
Реализация
loadMoreItems() должна гарантировать, что при повторных вызовах onAppear не будет запускаться несколько запросов на разбиение на страницы до завершения предыдущего запроса.🔹 Заключение
Использование специальной строки загрузки — это простой и предсказуемый способ реализации разбиения на страницы с помощью
List в SwiftUI.Запуская переход на следующую страницу, когда эта строка становится видимой, мы можем создать эффект бесконечной прокрутки, который легко понять и расширить.
#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
На WWDC 2025 Apple показала одну из самых недооценённых вещей презентации —
Foundation Models Framework. Теперь iOS-разработчики получили доступ к системной языковой модели Apple буквально в несколько строк Swift-кода.Без OpenAI API. Без интернета. Без отправки данных в облако.
#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
Ежегодная конференция WWDC от Apple в 2026 году пройдёт с 8 по 12 июня. Мероприятие откроет традиционная презентация новинок, а следом пользователей ждёт серия более детальных докладов о новинках.
Apple уже начала рассылать приглашения журналистам, а слоганом WWDC стала фраза Coming bright up («На подходе что-то яркое»). Ожидается, что компания в первую очередь представит обновления набора своих ОС: iOS 27, iPadOS 27, watchOS 27, macOS 27, tvOS 27 и visionOS 27. Кроме того, в пресс-релизе Apple упоминает новые инструменты на базе нейросетей.
Кроме основной программы в офисе Apple пройдут очные встречи для разработчиков, дизайнеров, студентов и финалистов конкурсов, включая Swift Student Challenge и Apple Design Awards.
Трансляция WWDC будет доступна на сайте компании, на портале Apple Developer, в фирменном приложении и на YouTube-канале для разработчиков.
#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Actomaton — это фреймворк для управления состоянием с использованием асинхронного подхода
async/await и Actor на Swift, вдохновленный Elm и swift-composable-architecture.Actomaton обеспечивает предсказуемый и потокобезопасный подход к управлению состоянием приложения и побочными эффектами в приложениях Swift.
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
Apple представила Container 1.0.0 — опенсорс-инструмент для запуска Linux-контейнеров на Mac. В отличие от привычного подхода, когда все контейнеры работают внутри общей виртуальной Linux-машины, Apple предлагает запускать каждый контейнер в отдельной облегчённой машине.
Проект полностью написан на Swift и оптимизирован под Mac на базе чипов Apple Silicon. Важно, что разработчики Apple решили не создавать закрытую экосистему и использовали привычные OCI-образы. Благодаря этому пользователи могут работать с образами из container registry, а собранные с помощью Container образы без проблем запускаются в других OCI-совместимых инструментах.
Смысл подхода Apple заключается в том, что для каждого контейнера создаётся отдельная легковесная виртуальная машина, а не одна общая для всего. В компании отмечают, что это даёт несколько преимуществ:
Управление инструментом осуществляется через CLI. С его помощью можно запускать контейнеры, собирать образы и работать с OCI-реестрами. В релизную версию добавили функцию
container machine для долгоживущих Linux-окружений с тесной интеграцией с хостом. Кроме того, проект перешёл на TOML-конфигурацию вместо системных настроек на базе UserDefaults.Apple отмечает, что воспринимать Container как замену Docker Desktop для всех сценариев пока рано. Проект только дошёл до версии 1.0, а часть привычных возможностей классических контейнерных инструментов всё ещё находится в разработке.
#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
В SwiftUI появился новый атрибут
ContentBuilder. По сути, это просто typealias для ViewBuilder, но сам факт его появления говорит об эволюции фреймворка. SwiftUI давно вышел за рамки простого построения вью — теперь мы строим тулбары, команды, вкладки, треки ключевых кадров, контент для композитора и многое другое.🔹 Старые специализированные билдеры
До появления
ContentBuilder SwiftUI использовал несколько специализированных билдеров:@ViewBuilder — для обычных вью@ToolbarContentBuilder — для тулбаров@CommandsBuilder — для команд@TabContentBuilder — для вкладок@KeyframeTrackContentBuilder — для треков анимации@CompositorContentBuilder — для контента композитораЭти имена точны, но раскрывают много деталей фреймворка прямо в месте вызова. Apple теперь описывает
ContentBuilder как унифицированную замену для тип-специфичных билдеров, таких как ToolbarContentBuilder и CommandsBuilder.🔹 Примеры использования
Для обычного контента вью:
@ContentBuilder
private func header() -> some View {
Text("Library")
.font(.title)
Text("Recently updated")
.foregroundStyle(.secondary)
}
То же самое можно использовать в кастомном контейнере:
struct Card<Content: View>: View {
private let content: Content
init(@ContentBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
VStack(alignment: .leading) {
content
}
.padding()
}
}Для тулбара (более интересный случай):
@ContentBuilder
private var editorToolbar: some ToolbarContent {
ToolbarItem {
Button("Undo") {}
}
ToolbarItem {
Button("Redo") {}
}
}
Здесь билдер больше не должен называться "toolbar" в месте объявления — тип результата (
some ToolbarContent) уже даёт всю необходимую информацию.🔹 Что не меняется
ContentBuilder не делает контент взаимозаменяемым. ToolbarItem не станет обычным View только потому, что замыкание использует @ContentBuilder. Окружающий тип параметра или возвращаемого значения по-прежнему определяет допустимый результат. Это граница безопасности:@ContentBuilder
private var toolbar: some ToolbarContent {
ToolbarItem {
Button("Save") {}
}
}
Билдер помогает конструировать контент, но не стирает разницу между
View, ToolbarContent, TabContent, Commands и другими протоколами SwiftUI.🔹 Доступность и миграция
Apple указывает доступность
ContentBuilder начиная с iOS 13, iPadOS 13, macOS 10.15, tvOS 13, watchOS 6 и visionOS 1. Для нового кода на новом SDK стоит использовать ContentBuilder в тех местах, где API действительно работает с обобщённым SwiftUI-контентом:init(@ContentBuilder content: () -> Content)
Это читается лучше, чем
@ViewBuilder, когда контент не ограничен только вью.🔹 Почему это важно для компилятора
Apple документирует
ContentBuilder как typealias для ViewBuilder, но также отмечает важную деталь реализации: его build-функции не принуждают к конформности протоколов напрямую. Типобезопасность сохраняется через условные соответствия на результирующих типах контента.Это имеет значение, потому что SwiftUI-код часто даёт типчекеру много контекстуальной работы: билдеры, перегруженные API, обобщённые типы контента и выведенные типы возврата — всё встречается в одном выражении.
ContentBuilder не решает магически все проблемы проверки типов, но соответствует направлению последних работ компилятора Swift: уменьшить ненужную неоднозначность и сделать решение ограничений менее дорогим в типичном SwiftUI-коде.🔹 Итог
ContentBuilder — маленькое API, но оно указывает на реальный рефакторинг в SwiftUI. У фреймворка теперь много видов декларативного контента, и вью — только один из них. ToolbarContentBuilder, TabContentBuilder, CommandsBuilder делали это разнообразие видимым, но также фрагментировали поверхность билдеров.ContentBuilder даёт SwiftUI одно общее слово для этих замыканий. Тип результата всё ещё сохраняет строгость правил, так что View, ToolbarContent, TabContent и другие типы контента не становятся взаимозаменяемыми.Хорошая новость в том, что это не только чистка нейминга. Типобезопасность сохраняется через условные соответствия на результирующих типах билдеров, что делает API шире, но не менее
#АрхитектурныйКод #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
Многие iOS-приложения содержат сторонние зависимости, такие как SDK для аналитики, сетевые библиотеки или инструменты для сбора отчетов о сбоях. Некоторые из этих зависимостей могут собирать данные или получать доступ к API, влияющим на конфиденциальность.
Манифесты конфиденциальности помогают сделать такое поведение более прозрачным. В этом посте мы рассмотрим, что такое манифесты конфиденциальности, как они связаны со сторонними SDK и что означают API с требуемыми основаниями для заявлений о конфиденциальности.
Давайте приступим.
🔹 Что такое манифест конфиденциальности?
Манифест конфиденциальности — это файл, в котором в стандартном формате описывается поведение приложения или SDK, связанное с конфиденциальностью.
Файл называется
PrivacyInfo.xcprivacy и добавляется в цель приложения или в SDK. В нем может содержаться такая информация, как:Чтобы добавить его в Xcode, мы можем выбрать
Файл -> Создать -> Файл и выбрать Конфиденциальность приложения шаблон файла. Xcode создает файл с именем PrivacyInfo.xcprivacy, который должен быть включен в целевое членство приложения или SDK, декларирующего политику конфиденциальности.Манифест конфиденциальности сам по себе не собирает данные и не меняет поведение приложения во время работы. Это файл с декларацией, который помогает описать, что делает приложение или SDK с точки зрения конфиденциальности.
Например, если приложение отправляет адрес электронной почты пользователя на серверную часть для работы с аккаунтом и использует
UserDefaults для хранения настроек приложения, манифест может содержать такие записи:<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeEmailAddress</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
В этом примере указано, что приложение не использует собранные данные для отслеживания, собирает адрес электронной почты для работы приложения и обращается к
UserDefaults с указанием необходимой категории API.В Xcode файл можно редактировать как список свойств, поэтому обычно нам не приходится писать XML вручную.
🔹 Заявления о конфиденциальности и сторонние SDK
Заявления о конфиденциальности особенно важны для сторонних SDK, поскольку поведение приложения в отношении конфиденциальности не ограничивается его собственным исходным кодом.
Если мы интегрируем SDK для аналитики, SDK для отчетов о сбоях, SDK для аутентификации или другую зависимость, этот код также может собирать данные или получать доступ к API, влияющим на конфиденциальность. Манифест конфиденциальности делает эту информацию более наглядной, показывая, что декларирует SDK и соответствует ли это тому, как мы используем SDK в приложении.
🔹 Создание отчета о конфиденциальности в Xcode
После архивирования приложения мы можем использовать Xcode для создания отчета о конфиденциальности.
Отчет о конфиденциальности — это сводная информация для разработчиков. Она помогает нам проверять заявления о конфиденциальности в приложении и его встроенных зависимостях перед отправкой приложения. Эта информация может использоваться для обеспечения точности маркировки конфиденциальности в App Store.
🔹 Необходимые API
Необходимые API — это API, которые Apple считает чувствительными к вопросам конфиденциальности, поскольку они потенциально могут использоваться для снятия цифровых отпечатков.
Снятие цифровых отпечатков — это сбор данных об устройстве или пользователе и их объединение для идентификации пользователя в разных приложениях или на разных веб-сайтах. Некоторые API на первый взгляд не связаны с конфиденциальностью, но в сочетании с другими сигналами могут раскрыть полезную информацию об устройстве.
Примеры категорий API, для которых требуется обоснование:
Если приложение или SDK используют один из этих API, в манифесте конфиденциальности необходимо указать категорию API и обосновать его использование.
Пример объявления для использования
UserDefaults может выглядеть так:<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
Здесь
NSPrivacyAccessedAPICategoryUserDefaults обозначает категорию используемого API, а CA92.1 — код одобренной причины. В данном случае CA92.1 означает, что приложение обращается к UserDefaults для чтения или записи информации, которая используется только самим приложением, например локальных настроек или предпочтений.Это также относится к сторонним SDK. Даже если код нашего приложения не обращается напрямую к API, требующему указания причины, это может делать SDK. В таком случае в манифесте конфиденциальности SDK должно быть указано такое использование.
#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩1
Apple объявила, что проект Swift Package Index стал частью экосистемы компании. Сооснователя и разработчика проекта устроили на работу в компанию. Теперь он займётся развитием Swift-пакетов в составе команды Apple.
Swift Package Index появился более пяти лет назад как независимый и открытый сервис для поиска, проверки и оценки совместимости Swift-библиотек. К 2026 году система индексирует более 10 тыс. пакетов, тестирует их на разных версиях Swift, публикует документацию и помогает разработчикам оценивать надёжность зависимостей. Например, в прошлом году проект выполнил более 3,5 млн проверок совместимости пакетов.
Сейчас же стало известно, что Swift Package Index становится частью экосистемы Apple. Компания обещает не закрывать код и продолжать работать в привычном режиме. Проект станет основой для полноценного реестра Swift-пакетов. В будущем появятся цифровые подписи пакетов, механизм подтверждения разработчиков и другие функции для обеспечения безопасности цепочки поставок.
Вместе с этим, сооснователь проекта Дэйв Вервер (Dave Verwer) перешёл в Apple. Он продолжит развивать Swift Package Index. Вервер уже обновил данные в LinkedIn, отметив, что теперь занимает должность Senior Developer Advocate в команде Swift Package Ecosystem.
Новость не была неожиданной для сообщества. Apple начала активно поддерживать проект ещё в 2023 году и стала спонсировать разработку. Ещё одним косвенным подтверждением перехода стало недавнее решение Вервера продать свою рассылку iOS Dev Weekly другим авторам. Всё дело в том, что Apple традиционно не поддерживает публичность своих сотрудников.
#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
LoopScroll — контрол для бесконечной прокрутки в iOS, построенный на основе
UICollectionView. Поддерживает горизонтальную и вертикальную прокрутку, автоматическую прокрутку и привычный API делегата/источника данных.Особенности:
UICollectionView@objc#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
LNPopupController — это фреймворк для отображения контроллеров представлений в виде всплывающих окон для других контроллеров представлений, аналогично мини-плеерам Apple Music и Podcasts.
Фреймворк спроектирован как универсальное решение, подходящее для большинства сценариев, поэтому он реализован в виде категории для
UIViewController. Каждый контроллер представления может отображать всплывающую панель, закреплённую относительно нижнего элемента интерфейса.Для
UITabBarController и его подклассов панель по умолчанию закрепляется над панелью вкладок. Для UINavigationController и его подклассов — над панелью инструментов. В остальных контроллерах всплывающая панель отображается в нижней части экрана. Подклассы контроллеров представления также могут предоставлять собственные элементы для закрепления панели.Фичи
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Kinetics привносит естественное ощущение реальной физики в ваши анимации SwiftUI.
Разработанный на основе Swift 6 с строгим соблюдением принципов многопоточности, он предоставляет современную и безопасную основу для создания анимаций, которая реагируют на действия пользователя, учитывают границы и выглядят реалистично.
#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1🔥1