Библиотека мобильного разработчика | Android, iOS, Swift, Retrofit, Moshi, Chuck
9.17K subscribers
2.07K photos
99 videos
55 files
5.04K links
Все самое полезное для мобильного разработчика в одном канале.

По рекламе: @tproger_sales_bot

Учиться у нас: clc.to/QSTQcA

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gos
Download Telegram
🔍 Агентное программирование в Xcode 26.3

В недавней демонстрации Apple показала нечто, что можно назвать настоящим прорывом в работе инструментов для разработки. В Xcode 26.3 программирование — это уже не просто более быстрое написание кода на Swift. Теперь среда разработки может делегировать целые инженерные задачи автономным агентам, которые планируют, выполняют и дорабатывают функции почти так же, как это делал бы младший разработчик.

Цель проста: опишите, что вы хотите создать, а система сделает всю механическую работу за вас.

🔹 От идеи до работающей функции

В видео Apple показывает пример приложения, в котором отображаются достопримечательности по всему миру. Вместо того чтобы собирать все вручную, мы можем попросить агента добавить данные о погоде в реальном времени с помощью WeatherKit и отобразить прогноз на семь дней в новом стиле Liquid Glass.

С помощью этого простого запроса Xcode и агент:

🔘 изучил структуру проекта
🔘 просмотрел документацию Apple в поисках современных API
🔘 добавил необходимые права доступа для WeatherKit
🔘 создал уровень сервиса погоды
🔘 разработал новые представления SwiftUI для отображения текущих условий и прогнозов
🔘 скомпилировал проект и автоматически исправил ошибки сборки

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

Дело было не в самой генерации кода. Дело было в рабочем процессе. Агент вел себя как разработчик, который сначала изучает кодовую базу, затем решает, куда что добавить, а потом вносит изменения, если что-то не работает.

🔹 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 выпустила System Metrics

Команда разработчиков языка программирования 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()
}
}


➡️ Код Swift System Metrics опубликован на GitHub, а документация — на портале для разработчиков.

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👨‍💻 App Store Connect CLI — быстрая работа с App Store Connect API

App Store Connect CLI — быстрая, легковесная, со скриптами CLI-утилита для работы с App Store Connect API. Автоматизируйте рабочие процессы выпуска iOS, macOS, tvOS и visionOS из терминала, IDE или конвейера CI/CD. Работайте с TestFlight, сборками, отправкой, подписанием, аналитикой, скриншотами, подписками и многим другим. JSON-ориентированный подход, без интерактивных промптов.

💻 App Store Connect CLI на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🎮 NSCache в Swift: практическое руководство

Когда приложение начинает рендерить тяжёлые ленты, многократно парсить сложный текст или декодировать одни и те же ресурсы при каждом скролле, разница между «просто работает» и «работает плавно» часто кроется в правильно расположенном кэше.

На iOS для таких задач отлично подходит NSCache из Foundation. Это in-memory контейнер с привычным key-value интерфейсом, но с одной важной особенностью: он автоматически удаляет элементы, когда системе не хватает памяти.

🔹 Что такое NSCache и как он работает?

Похож на Dictionary, но спроектирован специально для кэширования. Ключевое свойство — автоматическая эвикция (удаление) при нехватке памяти. Идеально подходит для объектов, которые дорого создавать, но безопасно пересоздать.

Важные особенности:

🔘 Живёт только в памяти процесса. При завершении приложения кэш исчезает.
🔘 Попадание в кэш никогда не гарантировано — система может в любой момент удалить объекты.
🔘 Работает только с reference types (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)
🔘 Результаты сложных вычислений или парсинга
🔘 Артефакты предрасчёта layout'а

Правило простое: кэшируем то, что дорого производить, но безопасно пересоздать.

🔹 Где NSCake не нужен

Плохие кандидаты:

🔘 Данные, которые должны переживать перезапуск приложения
🔘 Кэш с привязкой ко времени (TTL) — 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 кэширование. Он быстрый, потокобезопасный и автоматически адаптируется к состоянию памяти.

Используйте, когда:

🔘 Объекты дорого создавать
🔘 Промахи кэша допустимы
🔘 Значения можно безопасно пересоздать

Избегайте, когда:

🔘 Нужна гарантированная сохранность данных
🔘 Требуются строгие правила удаления
🔘 Нужна HTTP-семантика кэширования

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

#АрхитектурныйКод #MiddlePath #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
🧠 SwiftUI Pro — помощник по SwiftUI для ИИ

SwiftUI Pro — агентский навык, помогающий ИИ-помощникам писать более умный, простой и современный SwiftUI, с рекомендациями по использованию API, дизайну, производительности и доступности. Охватывает навигацию, компоновку, анимацию, управление состоянием, VoiceOver, устаревшие API и многое другое, ориентируясь на ошибки, которые действительно допускают программисты с большим опытом.

Навык основан на рабочем файле АGENTS. md, а это значит, что вы можете привнести многолетний опыт и знания в выбранного вами агента всего за несколько минут. Он использует формат Agent Skills, поэтому бесперебойно работает с Claude Code, Codex, Gemini, Cursor и другими.

💻 SwiftUI Pro на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ Меняем состояние приложения во время отладки с помощью LLDB

При разработке 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) изменять нельзя — попытка присвоить новое значение вызовет ошибку.

🔵 Value types могут вести себя неожиданно — при работе со структурами в некоторых контекстах вы изменяете копию, и изменение может не примениться так, как ожидается.

🔵 Свойства SwiftUI могут не реагировать — например, @State не всегда надёжно изменяется через LLDB.

🔹 Автоматизация изменений с помощью действий брейкпоинта

Когда при воспроизведении бага нужно, чтобы переменная всегда имела определённое значение, можно настроить автоматическое действие на брейкпоинте:

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 — фреймворк логирования

CocoaLumberjack — это быстрая и простая, но при этом мощная и гибкая платформа для ведения логов, предназначенная для macOS, iOS, tvOS, watchOS и visionOS.

Фичи:

🔵 Быстрый — в большинстве случаев на порядок быстрее NSLog
🔵 Простой — настройка в одну строку, замена NSLog на DDLog без изменения синтаксиса
🔵 Мощный — один оператор логирования может отправляться нескольким логгерам одновременно (файл + консоль), легко создавать свои логгеры
🔵 Гибкий — настройка уровней логирования для каждого файла, логгера или конфигурации Xcode, динамическое изменение во время выполнения, архивация и сжатие логов, загрузка на сервер

💻 CocoaLumberjack на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩1😍1
🎮 Локальное тестирование in-app покупок через StoreKit

При работе с in-app покупками тестирование различных сценариев — важная часть разработки. StoreKit предоставляет локальную среду, которая позволяет симулировать покупки, подписки и краевые случаи без подключения к App Store Connect.

🔹 Обзор процесса

Чтобы тестировать покупки локально, нужно:

1. Создать и настроить StoreKit configuration file
2. Включить StoreKit testing в Xcode
3. Симулировать покупки и управлять транзакциями

🔹 StoreKit configuration files

Файл конфигурации (.storekit) определяет продукты и поведение подписок для локальной симуляции. StoreKit читает этот файл вместо общения с App Store.

Xcode поддерживает два типа файлов:

🔵 Local configuration — полностью определяется в Xcode. Полезен для первичной настройки продуктов или тестирования новых сценариев.

🔵 Synced configuration — связан с App Store Connect и отражает уже настроенные продукты. Не редактируется напрямую.

🔹 Создание конфигурационного файла

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
🧠 Когда SwiftUI-модификаторы держат память дольше, чем ожидалось

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

Что делать:

🔵 Заменить @State на @StateObject (если используете ObservableObject)
🔵 Или ослабить ссылку в замыкании:

.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 сам по себе может удерживать части навигационного дерева для производительности и восстановления состояния. Исчезновение вью не всегда означает деаллокацию.

При диагностике:

🔵 Переключайтесь вперёд-назад несколько раз
🔵 Вызывайте принудительную память в симуляторе
🔵 Используйте Memory Graph вместо того, чтобы полагаться только на отсутствие deinit

Если объект исчезает после последующих навигаций — это, вероятно, кэширование SwiftUI, а не утечка.

🔹 Правила, которые предотвращают большинство проблем

🔵 Используйте правильный property wrapper. Вью создаёт и владеет экземпляром класса → @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
🔍 Как реализовать постраничную навигацию с помощью списка в SwiftUI

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

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
🔖 Foundation Models в iOS 26

На WWDC 2025 Apple показала одну из самых недооценённых вещей презентации — Foundation Models Framework. Теперь iOS-разработчики получили доступ к системной языковой модели Apple буквально в несколько строк Swift-кода.

Без OpenAI API. Без интернета. Без отправки данных в облако.

👉 Читать статью

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#свежак #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🦢 WWDC26

Ежегодная конференция 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 — фреймворк для управления состоянием

Actomaton — это фреймворк для управления состоянием с использованием асинхронного подхода async/await и Actor на Swift, вдохновленный Elm и swift-composable-architecture.

Actomaton обеспечивает предсказуемый и потокобезопасный подход к управлению состоянием приложения и побочными эффектами в приложениях Swift.

💻 Actomaton на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👨‍💻 Apple выпустила инструмент Container для запуска Linux-контейнеров на Mac

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: одно имя для разных типов контента

В 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") {}
}
}


Билдер помогает конструировать контент, но не стирает разницу между ViewToolbarContentTabContentCommands и другими протоколами 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. У фреймворка теперь много видов декларативного контента, и вью — только один из них. ToolbarContentBuilderTabContentBuilderCommandsBuilder делали это разнообразие видимым, но также фрагментировали поверхность билдеров.

ContentBuilder даёт SwiftUI одно общее слово для этих замыканий. Тип результата всё ещё сохраняет строгость правил, так что ViewToolbarContentTabContent и другие типы контента не становятся взаимозаменяемыми.

Хорошая новость в том, что это не только чистка нейминга. Типобезопасность сохраняется через условные соответствия на результирующих типах билдеров, что делает API шире, но не менее

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#АрхитектурныйКод #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
🎮 Что нужно знать о манифестах конфиденциальности в iOS

Многие iOS-приложения содержат сторонние зависимости, такие как SDK для аналитики, сетевые библиотеки или инструменты для сбора отчетов о сбоях. Некоторые из этих зависимостей могут собирать данные или получать доступ к API, влияющим на конфиденциальность.

Манифесты конфиденциальности помогают сделать такое поведение более прозрачным. В этом посте мы рассмотрим, что такое манифесты конфиденциальности, как они связаны со сторонними SDK и что означают API с требуемыми основаниями для заявлений о конфиденциальности.

Давайте приступим.

🔹 Что такое манифест конфиденциальности?

Манифест конфиденциальности — это файл, в котором в стандартном формате описывается поведение приложения или SDK, связанное с конфиденциальностью.

Файл называется PrivacyInfo.xcprivacy и добавляется в цель приложения или в SDK. В нем может содержаться такая информация, как:

🔵 какие типы данных собираются
🔵 связаны ли собранные данные с пользователем
🔵 используются ли собранные данные для отслеживания
🔵 к каким API обращаются по необходимости

Чтобы добавить его в 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, для которых требуется обоснование:

🔵 API с меткой времени файла
🔵 API времени загрузки системы
🔵 API дискового пространства
🔵 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
🦢 Проект Swift Package Index перешёл под управление Apple, а его разработчика взяли на работу в компанию

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 — бесконечно прокручиваемая постраничная навигация

LoopScroll — контрол для бесконечной прокрутки в iOS, построенный на основе UICollectionView. Поддерживает горизонтальную и вертикальную прокрутку, автоматическую прокрутку и привычный API делегата/источника данных.

Особенности:

🔵 Бесконечная прокрутка — плавная перемотка элементов в обоих направлениях
🔵 Горизонтальная и вертикальная — переключение направления прокрутки с помощью одного свойства
🔵 Автоматическая прокрутка — настраиваемая автоматическая прокрутка на основе таймера
🔵 Привязка к странице — настраиваемая компоновка обеспечивает точную привязку к странице с учетом скорости нажатия
🔵 Источник данных и делегат — привычные протоколы в стиле UICollectionView
🔵 Совместимость с Objective-C — все публичные API доступны через @objc
🔵 Легковесный — нет внешних зависимостей, ~500 строк кода на Swift

💻 LoopScroll на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
⚙️ LNPopupController — всплывающие окна поверх других контроллеров представлений

LNPopupController — это фреймворк для отображения контроллеров представлений в виде всплывающих окон для других контроллеров представлений, аналогично мини-плеерам Apple Music и Podcasts.

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

Для UITabBarController и его подклассов панель по умолчанию закрепляется над панелью вкладок. Для UINavigationController и его подклассов — над панелью инструментов. В остальных контроллерах всплывающая панель отображается в нижней части экрана. Подклассы контроллеров представления также могут предоставлять собственные элементы для закрепления панели.

Фичи

🔵 Поддержка стеклянного дизайна iOS 26 с сохранением подходящего внешнего вида на предыдущих версиях iOS.
🔵 Поддержка iOS 13 и новее.
🔵 Распространение в виде Swift Package Manager-пакета для проектов на Swift и Objective-C.
🔵 Корректная интеграция с современным UIKit.
🔵 Есть реализация SwiftUI

💻 LNPopupController на GitHub

📌 Лучшие вакансии для мобильных разработчиков

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
⚙️ Kinetics — настраиваемые примитивы физического движения для SwiftUI

Kinetics привносит естественное ощущение реальной физики в ваши анимации SwiftUI.

Разработанный на основе Swift 6 с строгим соблюдением принципов многопоточности, он предоставляет современную и безопасную основу для создания анимаций, которая реагируют на действия пользователя, учитывают границы и выглядят реалистично.

💻 Kinetics на GitHub

🐸 Библиотека мобильного разработчика

#буст #iOS
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥1