В Apple Foundation Models предусмотрены два результата проверки доступности: модель готова к работе или возвращена причина недоступности — это описано в документации SystemLanguageModel. Поэтому начните не с агента, а с простой функции: введите текст, отправьте запрос и покажите ответ. Сначала проверьте среду разработки, а затем — доступность модели именно во время работы приложения.

Кому пригодится: если вы только осваиваете SwiftUI и хотите добавить генерацию текста в учебный проект.
Если вы уже умеете создавать простую страницу, но пока не вызывали Foundation Models.
Если вы учитесь без собственного совместимого Mac и рассматриваете удалённую машину для практики.

План на эту неделю: сначала запустите страницу с фиктивным ответом, затем добавьте вызов модели и отдельно проверьте обработку недоступности. Так вы поймёте, где именно возникла проблема, вместо того чтобы принять успешную сборку за успешное выполнение запроса.

Последняя проверка: 25 сентября 2026 года. API и системные требования сверены с документацией Apple Foundation Models, описанием доступности модели и требованиями Xcode.

Сначала разделите совместимость проекта и доступность модели

Для первого задания Apple Foundation Models и SwiftUI не требуют большого приложения: достаточно текстового поля, кнопки и места для результата. Но проверяйте три вещи отдельно: можно ли установить и запустить выбранную версию Xcode, запускается ли приложение на целевой системе и доступна ли на устройстве системная модель. Это разные проверки, и одна не подтверждает другую.

Вариант проверки Что она подтверждает Чего она не подтверждает
Проект собирается в Xcode Код прошёл проверку компилятором для выбранной конфигурации Что целевое устройство поддерживает вызов модели
Страница работает с тестовым текстом Поле, кнопка и отображение результата связаны с состоянием SwiftUI Что запрос действительно обработала модель
Проверка SystemLanguageModel сообщает доступность Приложение может перейти к попытке вызова системной модели Что любая последующая операция обязательно завершится без ошибки
Проверка возвращает недоступность Код должен показать понятное состояние вместо бесконечной загрузки Что проект бесполезен или что интерфейс нельзя продолжать разрабатывать

Требования к Xcode — отдельная часть задачи: сверяйте их с официальной страницей требований Xcode, а не с тем, что случайно удалось установить на компьютере. Наличие Xcode 27 в названии проекта или в учебном задании само по себе не говорит, что конкретный Mac подходит для запуска системной модели. Нужны проверка версии инструмента и отдельная проверка доступности на целевой системе.

Порядок помогает избежать типичной ловушки новичка: приложение собирается, значит, кажется, что всё готово. На практике сборка подтверждает корректность проекта, но не состояние модели. Даже успешный запуск интерфейса в симуляторе не следует автоматически считать доказательством реального выполнения системного запроса на нужном устройстве.

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

Этап страницы: от макета к управляемому состоянию

Сначала сделайте интерфейс, который можно проверить без модели. В учебной аналогии состояние страницы — это как лист с текущими ответами: вы меняете запись, а интерфейс показывает её новое значение. В SwiftUI для хранения такого состояния применяется @State; его назначение описано в документации SwiftUI о State.

На этом этапе нужны три элемента:

  • текстовое поле для вопроса;
  • кнопка, запускающая действие;
  • область для ответа или статуса.

Начните с простого статического ответа, чтобы проверить визуальную часть. Введите текст и убедитесь, что он отображается в поле. Нажмите кнопку и временно замените текст в области результата, например на «Запрос будет отправлен после проверки модели». Это не вызов Foundation Models, и интерфейс должен ясно показывать, что ответ тестовый.

Так вы изолируете ошибки. Если введённый текст не появляется или нажатие не меняет экран, проблема пока в связке состояния и интерфейса, а не в модели. Не добавляйте к этому первому экрану историю диалога, загрузку изображений, инструменты или сложные настройки: каждая новая часть усложняет поиск причины сбоя.

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

Этап вызова: от учебного вопроса к ответу модели

Для системного вызова импортируйте FoundationModels, создайте LanguageModelSession и передайте строку в respond(to:). Эти сущности описаны в справке по Foundation Models, документации LanguageModelSession и описании метода respond(to:).

Сессию можно представить как рабочую тетрадь одного разговора с моделью. Строка запроса — prompt — это вопрос или задание, которое вы передаёте на обработку. Для первого упражнения используйте только текст и один запрос: сначала важно связать ввод с вызовом и отобразить полученный результат.

Ниже — минимальный каркас. Перед использованием сверьте имена API с актуальной документацией Apple: детали интерфейса и доступности могут меняться.

import SwiftUI
import FoundationModels

struct ModelPracticeView: View {
    @State private var prompt = ""
    @State private var answer = ""
    @State private var status = "Введите короткий вопрос."
    @State private var isWorking = false

    var body: some View {
        VStack(spacing: 16) {
            TextField("Ваш вопрос", text: $prompt)
                .textFieldStyle(.roundedBorder)

            Button("Отправить") {
                Task {
                    await sendPrompt()
                }
            }
            .disabled(isWorking || prompt.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)

            Text(status)
            Text(answer)
                .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding()
    }

    @MainActor
    private func sendPrompt() async {
        let text = prompt.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !text.isEmpty else {
            status = "Сначала введите вопрос."
            return
        }

        switch SystemLanguageModel.default.availability {
        case .available:
            isWorking = true
            status = "Выполняется запрос…"
            defer { isWorking = false }

            do {
                let session = LanguageModelSession()
                let response = try await session.respond(to: text)
                answer = response.content
                status = "Ответ получен."
            } catch {
                status = "Не удалось получить ответ. Проверьте состояние модели и повторите тест."
            }

        case .unavailable(let reason):
            answer = ""
            status = "Системная модель сейчас недоступна: \(reason)"
        }
    }
}

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

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

Этап проверки: недоступность вместо бесконечной загрузки

В официальной модели доступности различаются причины, связанные с неподходящим устройством, выключенной Apple Intelligence и тем, что модель ещё не готова. Их перечень и смысл смотрите в документации Apple о причинах недоступности. Не объединяйте эти случаи с ошибкой компиляции: компилятор не сообщает, готова ли модель к запросу на устройстве.

В интерфейсе полезно различать как минимум следующие ситуации:

  • Устройство не подходит. Покажите, что реальный вызов нужно проверить на другом целевом устройстве. Не обещайте, что установка более новой версии Xcode изменит аппаратную совместимость.
  • Apple Intelligence выключена. Сообщите, что сначала требуется проверить соответствующую настройку системы. Не утверждайте, что приложение само может включить эту функцию.
  • Модель не готова. Покажите понятный статус и предложите повторить проверку позже, если это подходит задаче.
  • Ошибка во время запроса. Покажите отдельное сообщение о сбое операции. Не подменяйте его статусом «ответ получен».

Для более понятного учебного экрана сопоставьте официальные причины с собственными текстами для пользователя. Причину из API можно использовать при диагностике, а в интерфейсе объяснить, что делать дальше. Не выдавайте техническое название состояния за доказательство того, что запрос был успешно отправлен.

Можно ли продолжать страницу, если модель пока недоступна?

Да. Вы можете закончить интерфейс, подключить тестовый ответ и проверить состояния загрузки и ошибки без успешного вызова модели. Но помечайте такой результат как демонстрационный. Чтобы подтвердить настоящую генерацию, отдельно дождитесь состояния .available, отправьте запрос и проверьте полученное содержимое.

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

Подходит ли симулятор для итоговой проверки?

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

Этап приёмки: один вопрос, три отдельных результата

Проведите сквозной тест на коротком нейтральном запросе без личной или учебной конфиденциальной информации. Например, попросите объяснить простое понятие, которое не требует доступа к вашим файлам. Не меняйте одновременно устройство, запрос и код: иначе будет трудно понять, что повлияло на результат.

Проверяйте этапы по порядку:

  1. Ввод: текст остаётся в поле после набора, пустой запрос не запускается.
  2. Действие: нажатие кнопки меняет статус, повторное нажатие во время ожидания не запускает параллельные действия.
  3. Доступность: приложение показывает, что вернула проверка SystemLanguageModel.
  4. Запрос: при доступной модели вызывается respond(to:), а экран не изображает успех до получения ответа.
  5. Результат: полученный текст отображается, а ошибка запроса не маскируется прежним ответом.

Записывайте итоги раздельно: страница отображается; вызов был запущен; модель фактически вернула ответ. Если остановились на первом пункте, продолжайте работу над SwiftUI. Если доступность отсутствует, отладьте сообщение и сценарий возврата. Если модель доступна, но запрос завершается ошибкой, проверяйте обработку операции и сверяйте сигнатуры API с документацией.

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

Если у вас нет локального Mac

Без собственного Mac можно заранее подготовить логику экрана, план теста и кодовую структуру, но реальная проверка зависит от среды, куда вы загрузите и запустите проект. Удалённый Mac может дать доступ к macOS и Xcode, однако само подключение к удалённой машине не гарантирует поддержку системной модели. До начала работы выясните, можно ли проверить необходимые версии инструментов и доступность модели в конкретной выделенной среде.

Сравнивайте варианты по учебной задаче, а не только по способу доступа. Собственный Mac удобен, если вы регулярно разрабатываете и вам нужно постоянно тестировать проекты. Компьютер под управлением Windows позволяет продолжать изучать общие основы программирования и готовить часть материалов, но не заменяет проверку iOS-проекта в совместимой среде Mac. Удалённая машина полезна для ограниченного задания, если доступ к нужным инструментам и реальный тест модели подтверждены заранее.

Перед выбором просмотрите условия и тарифы VMSPIN и сопоставьте их со сроком учебного проекта. Если среда подходит по требованиям задания, заказ удалённого Mac может быть практичным способом выполнить проверку без покупки собственного компьютера. Но если вам нужна постоянная тяжёлая работа, локальные подключения к периферии или среда, которую нельзя прерывать, аренда может быть не самым удобным решением.

Главный компромисс текущего компьютера без Mac — нельзя подтвердить поведение macOS-приложения на целевом устройстве; симулятор не заменяет проверку реальной доступности; а удалённая среда требует заранее выяснить, подходит ли именно выделенный Mac. Если эти ограничения мешают сдать упражнение, выбирайте временный доступ только после уточнения версии системы и возможности выполнить реальный вызов Foundation Models. Так вы арендуете среду под конкретную проверяемую задачу, а не платите за предположение, что модель заработает сама собой.